Найдите Факториал!


74

Создайте самую короткую программу или функцию, которая находит факториал неотрицательного целого числа.

Факториал, представленный !как, определяется как таковой

n!:={1n=0n(n1)!n>0

В простом английском языке факториал 0 равен 1, а факториал n, где n больше 0, в n раз больше факториала на единицу, чем n.

Ваш код должен выполнять ввод и вывод, используя стандартные методы.

Требования:

  • Не использует никаких встроенных библиотек, которые могут вычислить факториал (включая любую форму eval)
  • Можно рассчитать факториалы для чисел до 125
  • Можно рассчитать факториал для числа 0 (равно 1)
  • Завершается менее чем за минуту для номеров до 125

Получается самое короткое представление, в случае ничьей выигрывает ответ, набравший наибольшее количество голосов.


10
Сколько из приведенных ответов может вычислить до 125! без целочисленного переполнения? Разве это не было одним из требований? Приемлемы ли результаты в виде экспоненциальных приближений (т. Е. 125! = 1,88267718 × 10 ^ 209)?
Ами

6
@SHiNKiROU, даже golfscript может обойтись 125! менее 1/10 секунды и это и интерпретируемый язык!
gnibbler

5
@ugoren двухсимвольное решение другого вопроса использует встроенную факториальную функцию. Это не разрешено в этой версии испытания.
Майкл Стерн

4
Завершение менее чем за минуту кажется очень аппаратно-зависимым требованием. Завершается в течение минуты на каком оборудовании?
Сергиол

4
@sergiol Невероятно, но это не было проблемой в последние 2 года, я подозреваю, что большинство языков могут сделать это менее чем за минуту.
Кевин Браун

Ответы:


66

Golfscript - 12 символов

{,1\{)*}/}:f

Начало работы с Golfscript - Факториал шаг за шагом

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

Поэтому мы хотим опробовать наш новый инструмент golfscript . Всегда хорошо начинать с чего-то простого, поэтому мы начинаем с факториала. Вот начальная попытка, основанная на простом императивном псевдокоде:

# pseudocode: f(n){c=1;while(n>1){c*=n;n--};return c}
{:n;1:c;{n 1>}{n c*:c;n 1-:n;}while c}:f

Пробелы в гольскрипте очень редко используются. Самый простой способ избавиться от пробелов - использовать разные имена переменных. Каждый токен может использоваться как переменная (см. Страницу синтаксиса ). Полезные маркеры для использования в качестве переменных специальные символы , такие как |, &, ?- вообще ничего не используется в других местах в коде. Они всегда анализируются как токены одного символа. Напротив, переменные типа like nпотребуют пробела для добавления числа в стек после. Числа по существу являются преинициализированными переменными.

Как всегда, будут утверждения, которые мы можем изменить, не влияя на конечный результат. В golfscript, все оценивается как истина , за исключением 0, [], ""и {}(см это ). Здесь мы можем изменить условие выхода из цикла на простое {n}(мы добавляем цикл в дополнительное время и завершаем работу, когда n = 0).

Как и при игре в гольф на любом языке, это помогает узнать о доступных функциях. К счастью, список очень короток для гольфа. Мы можем изменить , 1-чтобы (спасти другой персонаж. В настоящее время код выглядит следующим образом: (мы могли бы использовать 1вместо этого, |если бы мы хотели, что бы сбросить инициализацию.)

{:n;1:|;{n}{n|*:|;n(:n;}while|}:f

Важно правильно использовать стек, чтобы получить кратчайшие решения (практика, практика). Как правило, если значения используются только в небольшом сегменте кода, может не потребоваться сохранять их в переменных. Удаляя переменную product product и просто используя стек, мы можем сохранить довольно много символов.

{:n;1{n}{n*n(:n;}while}:f

Вот о чем еще подумать. Мы удаляем переменную nиз стека в конце тела цикла, но затем добавляем ее сразу после. Фактически, перед началом цикла мы также удаляем его из стека. Вместо этого мы должны оставить его в стеке, и мы можем оставить условие цикла пустым.

{1\:n{}{n*n(:n}while}:f

Может быть, мы можем даже полностью исключить переменную. Для этого нам нужно будет постоянно хранить переменную в стеке. Это означает, что нам нужно две копии переменной в стеке в конце проверки условия, чтобы мы не потеряли ее после проверки. Это означает, что у нас будет избыточность 0в стеке после окончания цикла, но это легко исправить.

Это приводит нас к нашему оптимальному whileциклическому решению!

{1\{.}{.@*\(}while;}:f

Теперь мы все еще хотим сделать это короче. Очевидной целью должно быть слово while. Глядя на документацию, есть две жизнеспособные альтернативы - развернуть и сделать . Если у вас есть выбор различных маршрутов, попробуйте взвесить преимущества обоих. Развернуть это «довольно много времени цикла», так что в качестве оценки мы сократим 5 символов whileна 4 в /. Что касается do, мы разрезаем whileна 3 символа и получаем объединение двух блоков, что может сохранить еще один или два символа.

На самом деле есть большой недостаток в использовании doцикла. Поскольку проверка условия выполняется после однократного выполнения тела, значение 0будет неправильным, поэтому нам может понадобиться оператор if. Я вам сейчас скажу, что разворачивается короче ( doв конце представлены некоторые решения с ). Попробуйте и попробуйте, код, который у нас уже есть, требует минимальных изменений.

{1\{}{.@*\(}/;}:f

Большой! Наше решение теперь очень короткое, и мы здесь, верно? Нет. Это 17 символов, а у J 12 символов. Никогда не признай поражение!


Теперь вы думаете с ... рекурсией

Использование рекурсии означает, что мы должны использовать ветвящуюся структуру. К сожалению, но так как факториал можно выразить так кратко, рекурсивно, это кажется жизнеспособной альтернативой итерации.

# pseudocode: f(n){return n==0?n*f(n-1):1}
{:n{n.(f*}1if}:f # taking advantage of the tokeniser

Ну, это было легко - если бы мы попробовали рекурсию раньше, мы могли бы даже не взглянуть на использование whileцикла! Тем не менее, мы только на 16 символов.


Массивы

Массивы обычно создаются двумя способами - с помощью [и ]символов, или с ,функцией. Если выполняется с целым числом в верхней части стека, ,возвращает массив этой длины с arr [i] = i.

Для перебора массивов у нас есть три варианта:

  1. {block}/: толкать, блокировать, толкать, блокировать, ...
  2. {block}%: [push, block, push, block, ...] (здесь есть некоторые нюансы, например, промежуточные значения удаляются из стека перед каждым push)
  3. {block}*: толкать, толкать, блокировать, толкать, блокировать, ...

В документации по гольфу есть пример использования {+}*для суммирования содержимого массива. Это говорит о том, что мы можем использовать, {*}*чтобы получить произведение массива.

{,{*}*}:f

К сожалению, не все так просто. Все элементы отключены одним ( [0 1 2]вместо [1 2 3]). Мы можем использовать, {)}%чтобы исправить эту проблему.

{,{)}%{*}*}:f

Ну, не совсем. Это не обрабатывает ноль правильно. Мы можем вычислить (n + 1)! / (N + 1), чтобы исправить это, хотя это стоит слишком дорого.

{).,{)}%{*}*\/}:f

Мы также можем попытаться обработать n = 0 в том же сегменте, что и n = 1. Это на самом деле очень коротко, попытаться выработать как можно меньше.

Не так хорошо , как сортировка, в 7 символов: [1\]$1=. Обратите внимание, что этот метод сортировки имеет полезные цели, такие как наложение границ на число (например, `[0 \ 100] $ 1 =).
Вот победитель, имеющий только 3 символа:.! +

Если мы хотим, чтобы приращение и умножение были в одном и том же блоке, мы должны выполнять итерации по каждому элементу в массиве. Поскольку мы не создаем массив, это означает, что мы должны его использовать {)*}/, что приводит нас к кратчайшей реализации факториала в golfscript! В 12 символов, это связано с J!

{,1\{)*}/}:f


Бонусные решения

Начиная с простого ifрешения для doцикла:

{.{1\{.@*\(.}do;}{)}if}:f

Мы можем выжать пару лишних из этого. Немного сложно, так что вам придется убедить себя, что эти работы. Убедитесь, что вы понимаете все это.

{1\.!!{{.@*\(.}do}*+}:f
{.!{1\{.@*\(.}do}or+}:f
{.{1\{.@*\(.}do}1if+}:f

Лучшей альтернативой является вычисление (n + 1)! / (N + 1), что устраняет необходимость в ifструктуре.

{).1\{.@*\(.}do;\/}:f

Но самое короткое doрешение здесь занимает несколько символов, чтобы отобразить 0 к 1, и все остальное для себя - так что нам не нужно никаких ветвлений. Этот вид оптимизации чрезвычайно легко пропустить.

{.!+1\{.@*\(.}do;}:f

Для тех, кто заинтересован, здесь представлено несколько альтернативных рекурсивных решений такой же длины, как указано выше:

{.!{.)f*0}or+}:f
{.{.)f*0}1if+}:f
{.{.(f*}{)}if}:f

* примечание: на самом деле я не тестировал многие фрагменты кода в этом посте, поэтому не стесняйтесь сообщать, если есть ошибки.


8
Интересно, что, похоже, ошибка в уценке спойлера, когда вы используете код в спойлере ... Кто-нибудь хочет упомянуть об этом в Meta?
Иво Флипс

5
Мне интересно, как golfscript - язык игры в гольф - позволяет использовать имена из нескольких букв и «наказывает» вас за использование 1 буквы с необходимым пробелом
Cyoce

44

Хаскелл, 17

f n=product[1..n]

2
Я не знаю, Haskell ... Но будет ли это вычислять факториал для 0
Король

11
@ Король: да, будет. [1..0] ==> []иproduct [] ==> 1
JB

5
Я бы сказал, что для этого используется «встроенная библиотека», которую проблема запрещает. Тем не менее, другой метод также f 0=1;f n=n*f$n-1содержит 17 символов.
вечный

5
@eternalmatt: эта часть ограничений мне не указана. И, productи, скажем, (*)или (-)«можно рассчитать факториал», и все они определены с помощью Prelude. Почему один будет классным, а не другой?
JB

2
@YoYoYonnY: Я тоже считаю 17 символов, чтобы было меньше (субъективно) читабельности. ИМХО это нормально в комментариях.
JB

41

Python - 27

Просто:

f=lambda x:0**x or x*f(x-1)

22
Хороший трюк 0**x.
Александру

Как насчет math.factorial? Это не встроенный, не так ли?

1
@JackBates, который считается встроенным, так как вы не написали код для вычисления факториала.
FlipTack

1
Может кто-нибудь сказать мне, что за хитрость позади 0**x?
Павитра

1
@Pavitra: 0 0 = 1, и это первое, что оценивается, поэтому возвращается. Для любого другого n, 0 n = 0, таким образом, первый операнд или является ложным, так что второй операнд оценивается.
Mega Man

29

APL (4)

×/∘⍳

Работает как анонимная функция:

    ×/∘⍳ 5
120

Если вы хотите дать ему имя, 6 символов:

f←×/∘⍳

Я не говорю на APL, что здесь происходит?
Майкл Стерн

@MichaelStern: делает вектор индекса, т.е. ⍳5есть 1 2 3 4 5. ×(очевидно) умножить, /уменьшить, и является композицией функций. Итак, ×/∘⍳это функция, которая принимает аргумент xи дает произведение чисел [1..x].
Маринус

Ах, тот же подход, что и в решении @Yves Klett's Mathematica. Очень хорошо.
Майкл Стерн

@NBZ: Этого еще не было ни в 2011 году, когда был написан этот вопрос, ни в 2012 году, когда я писал этот ответ. Поезда были добавлены только в Dyalog 14.0, который вышел в 2014 году.
marinus

19

J (12)

Стандартное определение в J:

f=:*/@:>:@i.

Менее 1 секунды на 125!

Например:

 f 0
 1
 f 5
 120
  f 125x
 1882677176888926099743767702491600857595403
 6487149242588759823150835315633161359886688
 2932889495923133646405445930057740630161919
 3413805978188834575585470555243263755650071
 31770880000000000000000000000000000000

почему не просто * />: я. ?
Andbdrew

Поскольку OP запрашивает функцию, и лучшее, что мы можем сделать в J, это определить глагол.
Eelvex

2
Нет причин, по которым это не может быть анонимной функцией, верно? Как ([:*/1+i.)для 10 баллов или даже 8, так как скобки нужны только для вызова функции, а не для определения.
jpjacobs

в последнем, f 125xчто делает x? Это особый вид номера?
Cyoce

@Cyoce, да, это расширенная целочисленная точность .
Eelvex

17

Golfscript - 13 символов (SYM)

определяет функцию !

{),()\{*}/}:!             # happy robot version \{*}/ 

альтернативная версия на 13 символов

{),()+{*}*}:! 

вся версия программы 10 символов

~),()+{*}*

Тестовые случаи занимают менее 1/10 секунды:

вход:

0!

выход

1

вход

125!

выход

188267717688892609974376770249160085759540364871492425887598231508353156331613598866882932889495923133646405445930057740630161919341380597818883457558547055524326375565007131770880000000000000000000000000000000

1
+1 для символического входа в гольф! Хотелось бы, чтобы я проголосовал не раз. :-D
Крис Шестер-Янг

@ ChrisJester-Young, я сделаю это для тебя.
Cyoce

13

Perl 6: 13 символов

$f={[*]1..$_}

[*]такой же, как у Haskell product, и 1..$_считается от 1 до $_аргумента.


2
Запрещено больше не использовать пробел [*](сообщение об ошибке «Два члена подряд»).
Конрад Боровски

Вам не нужно устанавливать переменную, пустой блок кода является приемлемым ответом, поскольку он неявно формирует функцию. Также это все еще работает для 0?
Фил Х

10

Матлаб, 15

f=@(x)prod(1:x)

Тестовые случаи

>> f(0)
ans =
     1
>> f(4)
ans =
    24
>> tic,f(125),toc
ans =
  1.8827e+209
Elapsed time is 0.000380 seconds.

10

Python, 28 байт

f=lambda x:x/~x+1or x*f(x-1)

(на основе решения Александру)


9

MATL , 2 байта

:p

Разъяснение:

:    % generate list 1,2,3,...,i, where i is an implicit input
p    % calculate the product of of all the list entries (works on an empty list too)

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



Я собирался опубликовать именно это :-) Вы можете изменить ссылку, чтобы включить код и пример ввода
Луис Мендо

Как вы командуете, мой лорд.
flawr

4
@AndrasDeak, нет, это вывело бы все числа от 1 до i ...
YoYoYonnY

8

Рубин - 21 символ

f=->n{n>1?n*f[n-1]:1}

Контрольная работа

irb(main):009:0> f=->n{n>1?n*f[n-1]:1}
=> #<Proc:0x25a6d48@(irb):9 (lambda)>
irb(main):010:0> f[125]
=> 18826771768889260997437677024916008575954036487149242588759823150835315633161
35988668829328894959231336464054459300577406301619193413805978188834575585470555
24326375565007131770880000000000000000000000000000000

8

Ява, 85 символов

BigInteger f(int n){return n<2?BigInteger.ONE:new BigInteger(""+n).multiply(f(n-1));}

1
Это пропускает импорт: import java.math.*;(так, +19 байт).
Оливье Грегуар,

Честная оценка. ............
st0le

7

PostScript, 26 символов

/f{1 exch -1 1{mul}for}def

Пример:

GS> 0 f =
1
GS> 1 f =
1
GS> 8 f =
40320

Сама функция занимает всего 21 символ; остальное - привязать его к переменной. Чтобы сохранить байт, можно также привязать его к цифре, например так:

GS> 0{1 exch -1 1{mul}for}def
GS> 8 0 load exec =
40320

1
Ghostscript не может обработать 125 !; что-нибудь за 34! выходит как 1.#INF. (Я использовал акцию GNU Ghostscript 9.0.7 , скомпилированные для 64 - разрядной Windows.)
Росс Прижимной

7

JavaScript, 25

function f(n)!n||n*f(n-1)

CoffeeScript, 19

f=(n)->!n||n*f(n-1)

Возвращает trueв случае n = 0, но JavaScript все равно приведет к 1.


Вам не нужен returnоператор в функции JavaScript?
Джастин Морган

Обновление: Святой дым, тебе не нужен return! Но почему нет?
Джастин Морган

Это JavaScript 1.8 ( developer.mozilla.org/en/new_in_javascript_1.8 ). Полное раскрытие, это работает только на Firefox!
Кейси Чу

1
Хорошо, я не знал об исключении оператора возврата для JavaScript 1.8. Кроме того, вы можете гарантировать 1 вместо true для случая n = 0 с кодом той же длины: function f(n)n?n*f(--n):1
Briguy37

10
ES6, 17: f=n=>!n||n*f(n-1)Возьми это, CoffeeScript!
Ry-

6

Рубин - 30 29 символов

def f(n)(1..n).inject 1,:*end

Контрольная работа

f(0) -> 1
f(5) -> 120

1
Вы можете поставить endсразу после :*без новой строки или точки с запятой.
sepp2k

1
Нет необходимости передавать 1 в вызов #inject. (1..10).inject :*# => 3628800
Догберт

1
@ Догберт, а для чего f(0)?
Nemo157

@ Nemo157, ах! забыл об этом.
Догберт

4
Более короткий использовать 1.9 синтаксис лямбда: f=->n{(1..n).inject 1,:*}. Назовите его f[n].
Майкл Коль

6

F #: 26 символов

Там нет встроенной функции продукта в F #, но вы можете сделать один со сгибом

let f n=Seq.fold(*)1{1..n}

6

C #, 20 или 39 символов в зависимости от вашей точки зрения

Как традиционный метод экземпляра (39 символов; проверено здесь ):

double f(int x){return 2>x?1:x*f(x-1);}

Как лямбда-выражение (20 символов, но см. Заявление об отказе от ответственности; проверено здесь ):

f=x=>2>x?1:x*f(x-1);

Мы должны использовать, doubleпотому что 125! == 1.88 * 10 209 , что намного выше, чем ulong.MaxValue.

Отказ от ответственности за количество символов лямбда-версии:

Если вы выполняете рекурсию в лямбде C #, вам, очевидно, придется хранить лямбда в именованной переменной, чтобы она могла вызывать себя. Но, в отличие от (например, JavaScript), лямбда с самообращением должна быть объявлена и инициализирована в предыдущей строке. Вы не можете вызывать функцию в том же операторе, в котором вы объявляете и / или инициализируете переменную.

Другими словами, это не работает :

Func<int,double> f=x=>2>x?1:x*f(x-1); //Error: Use of unassigned local variable 'f'

Но это делает :

Func<int,double> f=null;            
f=x=>2>x?1:x*f(x-1);  

Для этого ограничения нет веских причин, поскольку fего нельзя отменять во время его работы. Необходимость Func<int,double> f=null;строки - это причуда C #. Делает ли это справедливым игнорировать это при подсчете символов - решать читателю.

CoffeeScript, 21 19 символов для настоящих

f=(x)->+!x||x*f x-1

Протестировано здесь: http://jsfiddle.net/0xjdm971/


6

Брахилог , 7 6 байт

Делая диапазон и умножая его

Танки -1 байт для ов, имеющих идею использовать функцию max ()

;1⌉⟦₁×

объяснение

;1          --  If n<1, use n=1 instead (zero case)
  ⟦₁        --      Construct the range [1,n]
    ×       --      return the product of said range

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


Брахилог , 10 9 байт

рекурсия

≤1|-₁↰;?×

объяснение

            --f(n):
≤1          --  if n ≤ 1: return 1
|           --  else:
 -₁↰        --      f(n-1)
    ;?×     --            *n

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


1
Это работает для 6 байтов. Взятие ввода в качестве одиночного разрешено по умолчанию.
овс

@ovs спасибо. Но использование ;вместо ,позволяет только обычный числовой ввод. -1 байт в любом случае
Kroppeb

5

С (39 символов)

double f(int n){return n<2?1:n*f(n-1);}

3
Приятно. Но может спасти некоторых персонажей: double f(n){return!n?1:n*f(n-1);}- 33 символа .
Угорен

2
f(125)будет переполнен
JKabrg

4

D: 45 символов

T f(T)(T n){return n < 2 ? 1 : n * f(n - 1);}

Более разборчиво:

T f(T)(T n)
{
    return n < 2 ? 1 : n * f(n - 1);
}

Кулер (хотя и более длинная версия) - шаблонизированный, который делает все это во время компиляции ( 64 символа ):

template F(int n){static if(n<2)enum F=1;else enum F=n*F!(n-1);}

Более разборчиво:

template F(int n)
{
    static if(n < 2)
        enum F = 1;
    else
        enum F = n * F!(n - 1);
}

Тем не менее, одноименные шаблоны довольно многословны, так что вы не можете использовать их в код-гольфе очень хорошо. D уже достаточно многословен с точки зрения количества символов, чтобы быть достаточно плохим для гольф-кода (хотя на самом деле он действительно хорош при уменьшении общего размера программы для больших программ). Хотя это мой любимый язык, поэтому я полагаю, что с таким же успехом я мог бы попытаться увидеть, насколько хорошо я смогу это сделать в кодовом гольфе, даже если подобный GolfScript не лишен этого.


3
выньте пробел, и вы можете получить его до 36 символов
трещотка урод

@Cyoce Можешь объяснить?
YoYoYonnY

Добро пожаловать на сайт, @ user272735. Обратите внимание, что мы не редактируем решения людей, чтобы сделать улучшения здесь. Вместо этого мы оставляем комментарии, предлагающие эти улучшения, как это было выше.
Мохнатый

4

PowerShell - 36

Наивный:

filter f{if($_){$_*(--$_|f}else{1}}

Контрольная работа:

> 0,5,125|f
1
120
1,88267717688893E+209

4

Скала, 39 знаков

def f(x:BigInt)=(BigInt(1)to x).product

Большинство символов гарантируют, что BigIntиспользуются s, так что требование к значениям до 125 выполняется.


Некоторые более короткие варианты:(x:Int)=>(BigInt(1)to x).product def f(x:Int)=(BigInt(1)to x).product def f(x:BigInt)=(x.to(1,-1)).product def f(x:BigInt)=(-x to-1).product.abs
LRLucena

4

Javascript, ES6 17

f=n=>n?n*f(n-1):1

ES6:

  • Функция стрелки

ES6 моложе этой задачи, если я правильно помню, и поэтому не отвечаю требованиям.
lirtosiast

Что-то странное с условным оператором. Почему есть два двоеточия?
Qwertiy

@Qwertiy Вы правы, это была опечатка, спасибо.
Афонсу Матос,

4

PowerShell, 42 байта

(сохранил 2 символа, используя фильтр вместо функции )

filter f($x){if(!$x){1}else{$x*(f($x-1))}}

Выход:

PS C:\> f 0
1
PS C:\> f 5
120
PS C:\> f 1
1
PS C:\> f 125
1.88267717688893E+209

1
Это путь старо, но ... Можно сохранить больше 1 символа с помощью реверсирования если / другое: filter f($x){if($x){$x*(f($x-1))}else{1}}. И он может быть уменьшен до 36 символов, если он вызывается через конвейер, так как это фильтр (например 125|f):filter f{if($_){$_*($_-1|f)}else{1}}
Эндрю

4

Ракетка (схема) 40 35 29 байт

Вычисляет 0! быть 1, и вычисляет 125! в 0 секунд по таймеру. Регулярный рекурсивный подход

(define(f n)(if(= n 0)1(* n(f(- n 1)))))

Новая версия, чтобы превзойти общий lisp: умножает все элементы списка (так же, как это решение на Haskell)

(λ(n)(apply *(build-list n add1)))

Более новая версия, чтобы превзойти другое решение схемы и математическое решение другой ракетки, используя foldl вместо apply и используя range вместо buildlist

(λ(n)(foldl * n(range 1 n)))

4

Морнингтон Полумесяц , 1827 1698 символов

Я чувствовал, что изучаю новый язык сегодня, и это то, на чем я остановился ... (Почему я делаю это для себя?) Эта запись не будет выигрывать какие-либо призы, но она побеждает все 0 других ответов до сих пор, используя тот же язык!

Take Northern Line to Bank
Take Central Line to Holborn
Take Piccadilly Line to Heathrow Terminals 1, 2, 3
Take Piccadilly Line to Acton Town
Take District Line to Acton Town
Take District Line to Parsons Green
Take District Line to Bank
Take District Line to Parsons Green
Take District Line to Acton Town
Take District Line to Hammersmith
Take Circle Line to Aldgate
Take Circle Line to Aldgate
Take Metropolitan Line to Chalfont & Latimer
Take Metropolitan Line to Aldgate
Take Circle Line to Hammersmith
Take District Line to Acton Town
Take Piccadilly Line to Bounds Green
Take Piccadilly Line to Acton Town
Take Piccadilly Line to Bounds Green
Take Piccadilly Line to Acton Town
Take District Line to Acton Town
Take District Line to Bank
Take Circle Line to Hammersmith
Take District Line to Upminster
Take District Line to Parsons Green
Take District Line to Notting Hill Gate
Take Circle Line to Notting Hill Gate
Take Circle Line to Bank
Take Circle Line to Temple
Take Circle Line to Aldgate
Take Circle Line to Aldgate
Take Metropolitan Line to Chalfont & Latimer
Take Metropolitan Line to Chalfont & Latimer
Take Metropolitan Line to Aldgate
Take Circle Line to Hammersmith
Take District Line to Upminster
Take District Line to Bank
Take District Line to Upney
Take District Line to Upminster
Take District Line to Hammersmith
Take District Line to Upminster
Take District Line to Upney
Take District Line to Bank
Take Circle Line to Embankment
Take Circle Line to Embankment
Take Northern Line to Angel
Take Northern Line to Moorgate
Take Metropolitan Line to Chalfont & Latimer
Take Metropolitan Line to Moorgate
Take Circle Line to Moorgate
Take Northern Line to Mornington Crescent

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

Любой, кто путешествовал по Лондону, сразу же это поймет, поэтому я уверен, что мне не нужно давать полное объяснение.

Большая часть работы на старте заключается в обработке случая 0. После инициализации продукта в 1, я могу использовать это для вычисления max (input, 1), чтобы получить новый ввод, используя тот факт, что 0! = 1! Тогда основной цикл может начаться.

(РЕДАКТИРОВАТЬ: целая куча поездок была спасена путем удаления 1 из «Терминалов Хитроу 1, 2, 3» вместо генерации ее путем деления 7 (сестер) на себя. Я также использую более дешевый метод для генерации -1 в следующий шаг.)

В Mornington Crescent декрементирование стоит дорого (хотя и дешевле, чем сама Tube). Чтобы сделать вещи более эффективными, я генерирую -1, беря NOT из анализируемого 0 и сохраняю его в Hammersmith для большей части цикла.


Я вложил в это значительную работу, но поскольку это моя первая попытка игры в гольф в Морнингтон-Кресент (фактически моя первая попытка на любом языке), я ожидаю, что пропустил несколько оптимизаций здесь и там. Если вы сами интересуетесь программированием на этом языке (а почему бы и нет?), Esoteric IDE - с его режимом отладки и окном просмотра - просто необходимо!


3

Befunge - 2x20 = 40 символов

0\:#v_# 1#<\$v *\<
    >:1-:#^_$>\:#^_$

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

Например, чтобы вычислить факториал 125

555**   0\:#v_# 1#<\$v *\<
            >:1-:#^_$>\:#^_$    .@

Тестирование 0

0   0\:#v_# 1#<\$v *\<
        >:1-:#^_$>\:#^_$    .@

Я знаю, что это довольно старый, но я думаю, что это несколько короче и быстрее: &:!#@_>:# 1# -# :# _$>\# :#* _$.@(где & должно быть заменено вводом). Это 32 символа / байта
FliiFe

3

J - 6 символов

*/>:i.

Это считается? Я знаю, что это очень похоже на предыдущий пример J, но оно немного короче :)

Я новичок с J, но это очень весело!


3

В С (23 символа)

Это нарушает «особенность» GCC, которая делает счет последнего присваивания в качестве возврата, если возврат не указан.

f(a){a=a>0?f(a-1)*a:1;}

В правильном C, 28 символов

f(a){return a>0?f(a-1)*a:1;}

+1 за GCC "особенность". Я думаю , что GCC даже позволяет блокировать возвращаемое значение (помню , делать что - то подобное)0 == ({printf("Hello, world!"); 0;});
YoYoYonnY

3

Кона ( 11 6)

*/1.+!

K работает справа налево (по большей части), поэтому мы перечисляем x(составляем список / массив чисел от 0до x-1), добавляем 1к нему (список варьируется 0до x), затем умножаем все числа вместе. Если бы это не было требованием для вычисления 125!, я мог бы сохранить еще 1 байт, исключив .рядом с 1. В любом случае 125! вычисляется в миллисекундах:

  */1.+!125.
1.882677e+209

Вам не нужно много этого. K имеет карри, поэтому весь ответ становится */1.+!: 6 байтов.
kirbyfan64sos

@ kirbyfan64sos: Верно, и я отредактирую это. Я думаю, что когда я писал это ~ 18 месяцев назад, я все еще застрял на всем, что должно быть вызвано (то есть функция).
Кайл Канос
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.