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


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.