Разметка взаимных

21

Учитывая число n> 77 , напишите программу или функцию, которая находит набор различных положительных целых чисел, так что сумма набора равна n , а сумма обратных значений набора равна 1.

Пример для 80:

80 = 2 + 4 + 10 + 15 + 21 + 28 ⟶ 1/2 + 1/4 + 1/10 + 1/15 + 1/21 + 1/28 = 1

Ваша программа или функция должна (теоретически) работать для любых n <2 32 и не должна быть оправдана за ошибки округления с плавающей запятой. Отметим, что решения существуют для всех n> 77 .


Самый короткий код в байтах побеждает.

Есть бонусный стимул: я назначу награду за самое маленькое решение, которое работает для любого n и запускает log (n) . Для малых n оно должно быть быстрым (определяется на мое усмотрение). Да, это возможно

orlp
источник
3
Всегда ли гарантировано такое разложение? Любая теорема о числе, которая это гарантирует?
Луис Мендо
Кажется, что существует для всех n> 77. (Я не проверял каждую деталь.) Это должно было быть в описании вашего вызова ...
flawr
1
@ flawr, я предполагаю, что он не включил эту ссылку, потому что она выдаёт O(log n)алгоритм.
Питер Тейлор
1
Еще он должен был упомянуть, что этот набор существует для данного n. (И я нашел эту статью на первой странице, когда гуглил название.)
flawr
1
@ Flawr, мне понадобилось около 10 минут, чтобы найти его. Я попал на страницу с египетскими фракциями, и вы меня ниндзя за 10 секунд.
Питер Тейлор

Ответы:

3

Mathematica, 54 байта

Select[IntegerPartitions@#,Unequal@@#&&Tr[1/#]==1&,1]&

Примерно так же неэффективно, как это получается, но это решает n = 78примерно за 9 секунд.

Результат возвращается в виде списка, заключенного в одноэлементный список, например:

{{45, 12, 9, 5, 4, 3}}
Мартин Эндер
источник
Интересно, работает ли он для очень больших п.
njpipeorgan
@njpipeorgan Учитывая достаточно памяти и времени, да.
Мартин Эндер
Я нашел оценку длины IntegerPartition [n], которая имеет порядок exp (sqrt (n)), ~ 10 ^ 10 ^ 4,5 для n = 2 ^ 30. Я действительно не верю, что Mathematica (или даже любая архитектура) способна содержать массив.
njpipeorgan
@njpipeorgan Задача прямо заявляет, что алгоритм должен работать до 2 ^ 32 теоретически , а не практически (как обычно предполагается для кода игры в гольф, если только задача явно не требует, чтобы программа фактически завершила все входные данные за разумное количество времени и памяти ).
Мартин Эндер
4

Python 3, 7306 1995 байт

Это решение работает в log (n) сложности (насколько я могу судить).

def i(s,t):
 for n in s[::-1]:t=t.replace(*n)
 return [[]]*78+[list(bytearray.fromhex(a))for a in t.split(",")]
def f(n):
 g,h=lambda c,n:c+[[[2],[3,7,78,91]][n[len(c)]%2]+[i*2for i in c[-1]]],lambda n:[]if n<78 else h((n-[2,179][n%2])//2)+[n]
 v=h(n);c=[i([['g',',03040'],['h',',,0306080'],['i',',020'],['j','b0c1'],['k','21'],['l','60'],['m','30'],['n','141'],['o','k24'],['p',',g'],['q','618'],['r','0c0'],['s','1e'],['t',',0ml'],['u','283c'],['v','e0f1'],['w','2a38'],['x','80'],['y','a0'],['z','01'],['A','50'],['B','24'],['C','i40'],['D','plb1'],['E','gl'],['F','48'],['G','bre1'],['H','28'],['I','6k'],['J','416s'],['K',',040Al'],['L','90'],['M','2a'],['N','54'],['O','k6o'],['P','3c'],['Q','il'],['R','18'],['S','px'],['T','im'],['U','70'],['V','b1'],['W','23'],['X','pj'],['Y','hj'],['Z','0n']],'020lxycHTaRHCyf1517CyfneC91k51cCLdneQU912MCyf0dBiALyf2dClfPEyfneT9s2dELdneEjIgmLydHg5rd14BKLardsE3n8sQ9rd1517Q9rdneplmdRBgUmcRMC5sPEyf102bgA6sPE91z2miAj41IQmc0dRBQUen7spl31z82bT9RFT3wE7neMgmyf0dRBgUmaHMELc1b36EUdBMQLyfs2d,C710M2bgLardRHT3BFQ9rf0dPQ7rdBMQm9Rs2d,0mAl9100d142bE710M2bQmc0fRPtxarfn8sEc1k4sBTfnePExcwtxarf1k8BExcuT3kkT91663C51964,0mAl71k4BMELe12NTcRwQjOT820ltmarf1z8mExeRNCqBFtmyjIHKLa100ds2bQU91bM36garf1k4sBTcRBFgxarfwE91keB2dtUxcn8sME9nbs36gm9rduC5R78,0mAUyf0d14BME91kbB36QLc12AB2dgyjqkHEUeMNT9157eQU9RMFT8s78C8neuixLc1zk4AtUxc1z8Mmt8re0fn8sWhLyc1bH36pl8neu,Kxycsw,iAxc1420l,K8ren8NS9n81bs36hc0vz8WmYzqkmhyv2WBHhyVOHXkJoSjIwSjIuSvz4WASVZIAXZ6skmSj6oFXzOmplvcsW46D61csk46plv8WBFDqoF,tarvk8WBH,tyjkqoHhGqkN,tmvZ8sWmhVZqskmpc0vZ8WAXZqkAplbnImASbn6skwSbn6skuSVOwSVOupGONSbn6soFpyVkJk5aSj6sk78YJkuDkIP5aYOuhvzk4WBAhVzk416oA,tyjkJ265a,,0mxyjk41q53sYzIHmPXkqowXkqouhyVqoHFYz6omFhb0e1zqkmNSyVIP78YJ20klpyVOHwYk620olpc0vz8WBmFXzqomFpG61ckH38PhyjIP78Yz620kmlDkImLDzINUhGIuNDzIA78hb0e1ZIANYkqk366chG6oFNXkJkP5ahVZ6somFSb0e1620kNlhVk41qomADzIFLXkqso78pGqoFNXzkImP5a,tyjk620oHlhG620kNlXzqskm78,tjZqskHmPYqouFD6sku78YzqkNU,tjZqsomF')[v[0]]]
 for o in range(len(v)-1):c=g(c,v)
 return c[-1]

Вы можете проверить, что f(2**32 - 1)работает почти мгновенно

Я использовал эту статью о методе для его вычисления. С помощью этого метода существует огромный массив данных для предварительно определенных значений для n от 78 до 334 без четных чисел после 168. Я хотел превратить эти данные во что-то маленькое, и я не знал хороших алгоритмов сжатия, поэтому я сделал мой собственный.

Я сжал его, имея список правил замены строк. Я создал метод, который нашел правило замены строки, которое сократило бы большинство содержимого во всем, принимая во внимание определение правила. Затем я применял это рекурсивно, пока не смог создать больше правил (я использовал символы gz и AZ). Строка, которую я сделал для замены, представляла собой разделенный запятыми список шестнадцатеричных значений для каждого из чисел. В ретроспективе, преобразование их в их шестнадцатеричные значения, возможно, не было самым разумным выбором, вероятно, было бы короче оставить их в десятичном виде, поскольку наличие шестнадцатеричного числа сохраняло бы только трехзначные числа, но добавляло бы 0 для однозначных чисел.

В строке, где я установил c, вы можете увидеть список правил замены и текст, на котором он выполняется. Правила также должны применяться в обратном порядке, поскольку некоторые правила включают символы, созданные из других правил.

В этом коде также есть множество мест, где я мог бы сократить синтаксис, например, превратить список списков в один список, а затем использовать другой метод для доступа к правилам, чтобы заменить текст на

Кэмерон Аавик
источник
1
n=218выходы [2]это то, что ожидается ??
officialaimm
1
Нет, я пойму, почему это происходит чуть позже. Мои извенения. Может быть ошибка в данных, которые я изначально сжал.
Кэмерон Аавик
1

Haskell, 93 байта

import Data.List
import Data.Ratio
p n=[x|x<-subsequences[2..n],sum x==n,1==sum(map(1%)x)]!!0

Ужасно медленный 1, но он работает в постоянной памяти. Тривиальное решение: проверьте все подпоследовательности [2..n]на сумму и сумму взаимных.

Возвращение всех решений вместо одного на 3 байта короче: просто удалите !!0(будьте осторожны: время выполнения всегда будет вне графика).


1 Время выполнения зависит от того, насколько рано результат появится в списке подпоследовательностей. Лень Хаскелла останавливает поиск, если найдено первое совпадение. После компиляции p 89(result [3,4,6,9,18,21,28]:) запускается на моем (4-летнем) ноутбуке в 35 лет. Другие значения, даже меньшие, могут занять часы.

Ними
источник
0

Юлия, 77 байт

n->collect(filter(i->i==∪(i)&&sum(j->Rational(1,j),i)==1,partitions(n)))[1]

Это неэффективная лямбда-функция, которая принимает целое число и возвращает целочисленный массив. Чтобы вызвать его, присвойте его переменной.

Мы получаем разделы целого числа, используя partitions. Затем мы отфильтровываем набор разделов только с теми, у которых уникальные элементы имеют взаимные суммы, равные 1. Чтобы гарантировать отсутствие ошибок округления, мы используем Rationalтип Джулии для создания обратных ссылок . filterвозвращает итератор, поэтому мы должны collectпреобразовать его в массив. Это дает нам массив массивов (только с одним элементом), поэтому мы можем получить первое использование [1].

Теперь, когда я говорю неэффективно, я имею в виду это. Выполнение этого для n = 80 занимает 39.113 секунды на моем компьютере и выделяет 13.759 ГБ памяти.

Алекс А.
источник