Написание рациональных чисел как отношения факториалов простых чисел

19

Примечание: этот вызов был размещен в песочнице .

Вступление

Эта задача вдохновлена 2009 Putnam B1 , проблемой в конкурсе математики для студентов. Проблема заключается в следующем:

Покажите, что каждое положительное рациональное число может быть записано как частное от произведений факториалов (не обязательно различных) простых чисел. Например,

$ \ frac {10} 9 = \ frac {2! \ cdot 5!} {3! \ cdot 3! \ cdot 3!}. $

Вызов

Ваша задача состоит в том, чтобы взять в качестве входных данных пару относительно простых натуральных чисел, представляющих числитель и знаменатель положительного рационального числа (или только самого рационального числа), и вывести два списка (или массива и т. Д.) Простых чисел так, чтобы введенное рациональное число равно отношению произведения факториалов простых чисел в первом списке к произведению факториалов простых чисел во втором списке.

Примечания

  • Там не может быть никаких простых чисел, которые содержатся как в первом списке, так и во втором списке; однако, простое число может появляться столько раз, сколько нужно в любом списке.
  • Можно предположить, что каждый из входов (не строго) находится между 1 и 65535; однако нельзя предположить, что факториалы чисел, которые вам нужно вывести, будут в этом диапазоне.

Пример ввода и вывода

Вот примеры юридических входов и выходов.

input=>output
10,9 => [2,5],[3,3,3]
2,1 => [2],[]
3,1 => [3],[2]
1,5 => [2,3,2],[5]     (elements of a list may be in any order)
3,2 => [3],[2,2]
6,1 => [3],[]

Входы (2,2), (0,3), (3,0), (3,6) и (1,65536) являются недопустимыми (т. Е. Ваша программа не должна вести себя по-своему) ). Вот несколько примеров незаконных выводов:

1,2 => [2],[2,2] (2 is in both returned lists)
5,2 => [5],[2,4] (4 is not prime)
2,1 => [2],[1] (1 is not prime either)
3,2 => [3],[2] (3!/2! = 3, not 3/2)

счет

Это , поэтому выигрывает самая низкая оценка в байтах!

Карл Шильдкраут
источник
Нужно ли давать какое-то минимально рациональное рациональное объяснение, если есть несколько способов выразить ответ? Например 10/9= [2*5]/[3*3]= [(2!/1!) * (5!/4!)] / [(3!/2!) * (3!/2!)]= [2! * 5! * 2! * 2!] / [3! * 3! * 1! * 4!]= (2! * 2! * 2! *5!) / (3! * 3! * 4!).
Цифровая травма
@DigitalTrauma Нет; однако 4 не является простым, поэтому второй не будет действительным. Я верю (и могу написать доказательство в вопросе, если хотите), что любое представление уникально.
Карл Шильдкраут
Можно ли использовать входные данные в виде дроби, 10/9а не пары чисел 10и 9?
Миша Лавров
@MishaLavrov Конечно. Я отредактирую вопрос, чтобы отразить это.
Карл Шильдкраут
@CarlSchildkraut Спасибо - да, это помогает - я думал, что что-то упустил
Цифровая травма

Ответы:

5

05AB1E , 54 53 48 46 40 35 33 32 28 байт

[D¿÷Z#DÓ€gZD<ØŠQ*DˆR!*]¯øεʒĀ

Попробуйте онлайн! Редактировать: Сохранено 2 байта благодаря @ ASCII-only. Сохранено 1 2 3 4 байта благодаря @Emigna. (Мне нужно только сохранить еще один, и я уменьшил до половины моего первоначального числа байтов!) Объяснение:

[       Begin an infinite loop
D¿÷     Reduce to lowest terms
Z#      Exit the loop if the (largest) value is 1
DÓ€g    Find the index of the largest prime factor of each value
Z       Take the maximum
D<ØŠ    Convert index back to prime and save for later
Q       Convert to an pair of which value had the largest prime factor
*       Convert to an pair with that prime factor and zero
Dˆ      Save the pair in the global array for later
R!*     Multiply the other input value by the factorial of the prime
]       End of infinite loop
¯ø      Collect all the saved primes
εʒĀ     Forget all the saved 0s
Нил
источник
Я люблю "эмоциональные" сценарии -¦D
RedClover
46 байтов
только ASCII
39 байтов
г-н Xcoder
5

Mathematica, 175 177 169 154 108 байт

Join@@@Table[x[[1]],{s,{1,-1}},{x,r@#},x[[2]]s]&@*(If[#==1,1,{p,e}=Last@(r=FactorInteger)@#;p^e#0[p!^-e#]]&)

Попробуйте онлайн!

Как это устроено

Это композиция из двух функций. Первое, которое развязывает

If[# == 1,
  1,
  {p,e} = Last[FactorInteger[#]];
  p^e * #0[p!^-e * #]
]&

является рекурсивной функцией для фактического вычисления желаемой факторизации В частности, при рациональном вводе xмы вычисляем простые числа, чьи факториалы должны быть в числителе и знаменателе, и возвращаем дробь со всеми этими простыми числами, умноженными вместе. (Например, при вводе 10/9 = 2!*5!/(3!*3!*3!)мы возвращаемся 10/27 = 2*5/(3*3*3).)

Мы делаем это, имея дело с наибольшим простым множителем на каждом шаге: если p e возникает при факторизации x, мы проверяем p! e происходит в факториализационной факторизации, и рекурсивный на x делится на p! эл .

(Ранее у меня была более умная стратегия, которая избегает больших чисел, просматривая предыдущее простое число перед p, но Mathematica может легко обрабатывать числа размером до 65521!, Так что нет никакого смысла. Старая версия, которую вы можете найти в истории, это намного быстрее: на моем компьютере потребовалось 0,05 секунды на входы, которые эта версия обрабатывает за 1,6 секунды.)

Вторая функция превращает вывод первой функции в списки простых чисел.

Join @@@ 
  Table[x[[1]],
    {s,{1,-1}},
    {x,FactorInteger[#]},
    x[[2]]*s
  ]&

Для s=1(положительных степеней) и s=-1(отрицательных степеней) и для каждого члена {prime,exponent}факторизации r@#мы повторяем простое число prime exponent*sмного раз.

Неконкурентная версия с 109 62 байтами

If[#==1,∇1=1,{p,e}=Last@FactorInteger@#;(∇p)^e#0[p!^-e#]]&

То же, что и выше, но вместо выдачи вывода в виде списка, вывод выводится в виде выражения, используя оператор ((поскольку он не имеет встроенного значения) в качестве замены для факториалов. Таким образом, вход 10/9дает выход (∇2*∇5)/(∇3)^3для представления (2!*5!)/(3!)^3.

Это короче, потому что мы пропускаем вторую часть функции.


+2 байта: назначение f=Firstдолжно быть выполнено в нужном месте, чтобы Mathematica не расстраивалась.

-8 байт: исправлена ​​ошибка для целочисленных выходных данных, которая фактически делала код короче.

-15 байт: FactorIntegerвозвращает отсортированный вывод, которым мы можем воспользоваться.

-46 байт: нам не нужно быть умным.

Миша лавров
источник
2

Python 2, 220 202 195 183 байта

g=lambda a,b:a and g(b%a,a)or b;n,d=input();m=c=()
while n+d>2:
 t=n*d;f=p=2
 while t>p:
	if t%p:p+=1;f*=p
	else:t/=p
 if n%p:c+=p,;n*=f
 else:m+=p,;d*=f
 t=g(n,d);n/=t;d/=t
print m,c

Попробуйте онлайн! Изменить: Сохранено 18 25 байт благодаря @ Mr.Xcoder. Сохранено 12 байтов благодаря @JonathanFrech.

Нил
источник
202 байта
мистер Xcoder
Вы можете сократить его еще больше в Python 2, поскольку вы можете заменить несколько пробелов на табуляцию в отступе
Mr. Xcoder
189 байт .
Джонатан Фрех
183 байта .
Джонатан Фрех