Повторный поворот делителя


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 Я немного изменил формулировку, теперь она понятнее?
Згарб

@ Згарб извините, но нет, это не операция, вы определяете связь между числами. Если вы определяете отношение <для натуральных чисел, для каждого 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, кажется, задыхается при попытке sum ( 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

Ява, 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

Спасибо за прием и предложение! Да, мне потребуется некоторое время, чтобы разглядеть эти мелочи. Каждый байт имеет значение! Еще раз спасибо!
TNT

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

Говоря об этом, я не думаю, что мне нужно использовать addдважды. Постойте ...
TNT

Но второй цикл не нужен в целом. Если у вас есть то, aчто, как вы знаете, делит nчисто, то вам не стоит искать b, это просто n/a. В этот момент он начинает становиться все ближе и ближе к моему;)
Geobits

4

Ява, 157 121

Вот рекурсивная функция, которая получает потомков каждого потомка n. Возвращает 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
Насколько я понимаю, Octave может заканчивать блоки только с, 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элементы из этого списка, удаляет дубликаты и сортирует список. Вуаля.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.