Ітераційний поворот дільника


13

Визначення

Нехай mі nбудуть натуральними числами. Ми говоримо , що mє дільником твіст з , nякщо існує цілих чисел , 1 < a ≤ bтаких , що n = a*bі m = (a - 1)*(b + 1) + 1. Якщо mможе бути отримана з nзастосовуючи нуль або більше подільники завихрення до нього, то mє нащадок з n. Зауважте, що кожне число - це власний нащадок.

Наприклад, розглянемо n = 16. Ми можемо вибрати a = 2і b = 8, так як 2*8 = 16. Потім

(a - 1)*(b + 1) + 1 = 1*9 + 1 = 10

що показує, що 10це ділення повороту 16. З a = 2і b = 5, потім ми бачимо, що 7це перекрут дільника 10. Таким чином 7є нащадком Росії 16.

Завдання

Давши додатне ціле число n, обчисліть нащадків n, перелічених у порядку зростання, без дублів.

Правила

Вам заборонено використовувати вбудовані операції, які обчислюють дільники числа.

Приймаються як повні програми, так і функції, і повернення типу даних колекції (як-от набір певного типу) дозволено, якщо воно відсортовано і не дублює. Виграє найменший байт, а стандартні лазівки заборонені.

Випробування

1 ->  [1]
2 ->  [2] (any prime number returns just itself)
4 ->  [4]
16 -> [7, 10, 16]
28 -> [7, 10, 16, 25, 28]
51 -> [37, 51]
60 -> [7, 10, 11, 13, 15, 16, 17, 18, 23, 25, 28, 29, 30, 32, 43, 46, 49, 53, 55, 56, 60]

@ Zgarb, якщо ви дозволите, що ланцюжок із 0 поділок ділиться, то як не кожне число є нащадком будь-якого іншого числа?
rorlork

3
@rcrmn Мені ланцюг нульових операцій означає операцію ідентичності. Отже, якщо дозволити повороти нульового дільника, це означає лише те, що кожне число є нащадком.
Згарб

@ Zgarb добре, тому визначення слід змінити, щоб висловити це, бо якщо ні, наскільки я можу сказати, будь-яке число вважається нащадком кожного іншого числа. Я не знаю, для чого потрібна рефлексивність. Ви б хотіли пояснити?
rorlork

@rcrmn Я трохи змінив формулювання, чи зрозуміліше це зараз?
Згарб

@Zgarb Вибачте, але ні, це не операція, ви визначаєте співвідношення між числами. Якщо ви визначаєте відношення <для натуральних чисел, для кожного n ви отримуєте кожне число менше, ніж воно, але не саме воно. Я думаю, це має бути щось подібне. Таким чином, я думаю, що лише 4 були б його власним нащадком (хоча не впевнений у цьому).
rorlork

Відповіді:


9

Python 2, 109 98 85 82 байт

f=lambda n:sorted(set(sum(map(f,{n-x+n/x for x in range(2,n)if(n<x*x)>n%x}),[n])))

Оскільки (a-1)*(b+1)+1 == a*b-(b-a)і b >= aнащадки, завжди менше або дорівнює початковому числу. Тож ми можемо просто почати з початкового числа і продовжувати генерувати суворо менші нащадки, поки не залишиться жодного.

Умова (n<x*x)>n%xперевіряє дві речі в одному - те n<x*xі n%x == 0.

(Дякуємо @xnor за те, що він зняв 3 байти з базового корпусу)

Pyth, 32 байти

LS{s+]]bmydm+-bk/bkf><b*TT%bTr2b

Прямий переклад вищезазначеного, за винятком того, що, здається, Pyth задихається, намагаючись підвести суму ( s) до порожнього списку.

Це визначає функцію, yяку можна викликати, додавши y<number>в кінці, як-от так ( спробуйте в Інтернеті ):

LS{s+]]bmydm+-bk/bkf><b*TT%bTr2by60

CJam, 47 45 байт

{{:X_,2>{__*X>X@%>},{_X\/\-X+}%{F}%~}:F~]_&$}

Також використовуючи той самий метод, з кількома модифікаціями. Я хотів спробувати CJam для порівняння, але, на жаль, у CJam я набагато гірший, ніж у Pyth / Python, тому, мабуть, є багато можливостей для вдосконалення.

Вищевказане - це блок (в основному версія неназваних функцій CJam), який приймає int і повертає список. Ви можете перевірити його так ( спробуйте в Інтернеті ):

{{:X_,2>{__*X>X@%>},{_X\/\-X+}%{F}%~}:F~]_&$}:G; 60 Gp

Я не експерт Python, але чи є причина, чому вам потрібно set()там? Ви не можете просто повернути відсортований список?
Олексій А.

@Alex set()має видалити дублікати :)
Sp3000

О, гаразд. Акуратний. Хороша робота!
Олексій А.

Ви можете, можливо, зробити так, [n]+sum(...,[])як sum(...,[n])?
xnor

@xnor Ах так, я можу. Я ніколи не використовував нічого, окрім []базового випадку для підбиття списків, тому повністю забув!
Sp3000

6

Java, 148 146 104 байт

Версія для гольфу:

import java.util.*;Set s=new TreeSet();void f(int n){s.add(n);for(int a=1;++a*a<n;)if(n%a<1)f(n+a-n/a);}

Довга версія:

import java.util.*;
Set s = new TreeSet();
void f(int n) {
    s.add(n);
    for (int a = 1; ++a*a < n;)
        if (n%a < 1)
            f(n + a - n/a);
}

Тож я дебютував на PPCG з цією програмою, яка використовує TreeSet(яка автоматично сортує числа, на щастя) та рекурсії, подібні до програми Geobits, але по-іншому, перевіряючи кратність n і потім використовуючи їх у наступна функція. Я б сказав, що це досить справедливий бал для першокласника (особливо для Java, який, здається, не є найбільш ідеальною мовою для подібних речей, і допомога Geobits).


Ласкаво просимо до PPCG! Ви можете зберегти кілька змінивши , a*bщоб nна лінії 9.
Geobits

Дякуємо за привітання та пропозицію! Так, мені знадобиться певний час, щоб помітити ці дрібниці. Кожен байт рахується! Знову дякую!
ТНТ

Також можна зберегти ще два, помістивши c=n+a-bвсередину add(). Крім того, ви можете позбутися cзовсім і просто використовувати n+a-bв обох місцях для тих самих двох байтів.
Геобіт

Якщо говорити про це, я не думаю, що мені потрібно використовувати addдва рази. Зачекайте хвилинку ...
ТНТ

Але друга петля взагалі не потрібна. Якщо у вас є aте, що ви знаєте, ділиться nчисто, то вам не слід шукати цикл b, це просто n/a. У цей момент вона починає все ближче і ближче до моєї;)
Геобіт

4

Ява, 157 121

Ось рекурсивна функція, яку отримують нащадки кожного нащадка n. Він повертає a TreeSet, який сортується за замовчуванням.

import java.util.*;Set t(int n){Set o=new TreeSet();for(int i=1;++i*i<n;)o.addAll(n%i<1?t(n+i-n/i):o);o.add(n);return o;}

З деякими перервами рядків:

import java.util.*;
Set t(int n){
    Set o=new TreeSet();
    for(int i=1;++i*i<n;)
        o.addAll(n%i<1?t(n+i-n/i):o);
    o.add(n);
    return o;
}

2

Октава, 107 96

function r=d(n)r=[n];a=find(!mod(n,2:sqrt(n-1)))+1;for(m=(a+n-n./a))r=unique([d(m) r]);end;end

Симпатичний друк:

function r=d(n)
  r=[n];                          # include N in our list
  a=find(!mod(n,2:sqrt(n-1)))+1;  # gets a list of factors of a, up to (not including) sqrt(N)
  for(m=(a+n-n./a))               # each element of m is a twist
    r=unique([d(m) r]);           # recurse, sort, and find unique values
  end;
end

1
Це моє розуміння того, що Октав може закінчитися блоки тільки , endа не endforта endfunction. Це допоможе вам заощадити 11 байт.
Олексій А.

Гей, ви праві! Не те, як я вивчив мову і ніколи не зрозумів, що це можна зробити. Чому ти перший, хто вказав на це після того, як я зробив кілька гольфів з ним?
dcsohl

Я це знав лише тому, що нещодавно я подивився на нього, побачивши його в чужому гольфі з іншого питання. Я ніколи не використовував Octave, і минуло років, як я використовував Matlab. Я здогадуюсь, що на PPCG не так багато активних користувачів Octave, але я можу помилитися.
Олексій А.

Ну, дякую, що ви вказали на це.
dcsohl

Моє задоволення, рада, що можу допомогти. Приємне рішення.
Олексій А.

1

Haskell, 102 100 байт

import Data.List
d[]=[]
d(h:t)=h:d(t++[a*b-b+a|b<-[2..h],a<-[2..b],a*b==h])
p n=sort$nub$take n$d[n]

Використання: p 16які виходи[7,10,16]

Функція dрекурсивно обчислює всіх нащадків, але не перевіряє наявність дублікатів, тому багато хто з’являється не один раз, наприклад d [4]повертає нескінченний список 4s. Функції pприймають перші nелементи з цього списку, видаляє дублікати та сортує список. Voilà.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.