Вызов
Найдите выражение длиной не более 100 байт с самой длинной сигнатурой типа.
правила
- Разрешен любой статически типизированный язык с выводом типа
- Тип должен быть однозначным, но в противном случае он может включать типы без определенных экземпляров. Например
Num [a]
иEq [a]
разрешено, даже без определенного экземпляра - Нет импорта, кроме минимума, необходимого для компиляции программы с STDIN / STDOUT
- Бесконечные типы не допускаются
- Если ответ имеет более одного выражения, только один может внести свой вклад в оценку. Например, хотя типовая сигнатура композиции
(.) :: (b -> c) -> (a -> b) -> a -> c
, имеющая оценку 20, ответ с 25 копиями(.)\n
будет иметь оценку 20, а не 500 - Выражение должно быть не более 100 байтов
- Оценка - это количество символов в сигнатуре типа, исключая имя функции и любые пробелы. Например,
f :: (a -> b) -> a -> b
будет иметь оценку 12 - Самый высокий балл побеждает!
Примеры
Хотя допускаются и другие языки, в Haskell есть следующие примеры:
Score: 112
map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map
f :: (a -> b)
-> [[[[[[[[[[[[[[[[[[[[[[[[[a]]]]]]]]]]]]]]]]]]]]]]]]]
-> [[[[[[[[[[[[[[[[[[[[[[[[[b]]]]]]]]]]]]]]]]]]]]]]]]]
Score: 240
(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.)
f :: (b->c)->(a->a1->a2->a3->a4->a5->a6->a7->a8->a9->a10->a11->a12->a13->a14->a15->a16->a17->a18->a19->a20->a21->a22->a23->a24->b)->a1->a2->a3->a4->a5->a6->a7->a8->a9->a10->a11->a12->a13->a14->a15->a16->a17->a18->a19->a20->a21->a22->a23->a24->c
Score: 313
foldl$foldl$foldl$foldl$foldl$foldl$foldl$foldl$foldl$foldl$foldl$foldl$foldl$foldl$foldl$foldl(.)
f :: (Foldable t, Foldable t1, Foldable t2, Foldable t3, Foldable t4,
Foldable t5, Foldable t6, Foldable t7, Foldable t8, Foldable t9,
Foldable t10, Foldable t11, Foldable t12, Foldable t13,
Foldable t14, Foldable t15) =>
(b -> c)
-> t (t1 (t2 (t3 (t4 (t5 (t6 (t7 (t8 (t9 (t10 (t11 (t12 (t13 (t14 (t15 (b
-> b))))))))))))))))
-> b
-> c
Score: 538
lex.show.foldl1.mapM.traverse.sum.mapM.sum.traverse.(.).mapM.scanl.zipWith3((.traverse).(.traverse))
(Num
(a -> ([[c]] -> t3 [[a1 -> f b]]) -> [[c]] -> t3 [[a1 -> f b]]),
Num
(([[c]] -> t3 [[a1 -> f b]])
-> t1 (t2 ([[c]] -> t3 [[a1 -> f b]]))
-> [[c]]
-> t3 [[a1 -> f b]]),
Show
(t (t1 (t2 ([[c]] -> t3 [[a1 -> f b]])))
-> t1 (t2 ([[c]] -> t3 [[a1 -> f b]]))),
Applicative f, Foldable t,
Foldable ((->) (t1 (t2 ([[c]] -> t3 [[a1 -> f b]])) -> a)),
Foldable
((->) (([[c]] -> t3 [[a1 -> f b]]) -> a -> t3 [a1 -> f b])),
Traversable t1, Traversable t2, Traversable t3, Traversable t4,
Traversable t5,
Traversable ((->) (t1 (t2 ([[c]] -> t3 [[a1 -> f b]])))),
Traversable ((->) ([[c]] -> t3 [[a1 -> f b]]))) =>
[(t5 (t4 a1) -> f (t5 (t4 b))) -> c -> a1 -> f b]
-> [(String, String)]
code-challenge
busy-beaver
functional-programming
Майкл Кляйн
источник
источник
Ответы:
Хаскелл, ~ 2 ^ (2 ^ 18)
Каждое приложение
f
примерно удваивает сигнатуру типа путем преобразования сигнатуры типаT
в(T,T)
. Например, четырехкратная композицияf.f.f.f$0
имеет типКаждая строка в четыре раза превышает количество заявлений
f
, поданных4^9 = 2^18
в конце. Итак, подпись типа имеет размер порядка2^(2^18)
.источник
f x=(x,x,x)
за счет одногоn.
в последней строке дает оптимальный результат для этой общей структуры.n.
будет больше.2^18
против,3 * (2^16)
если я не ошибся при расчете первоначального возведения в степень:2^(4^9)
против3^((4^8)*3)
(,)
(или(,,)
) может быть использован для сохранения некоторых байтов и улучшения оценки, используя большеn
s.Ява, оценка 17301488
Требуется метод
<T>java.util.Map<T,T>f(T t){return null;}
, который был посчитан до 100-байтового предела.f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(1)))))))))))))))))))
Подпись типа времени компиляции этого должна соответствовать этому.
источник
Попробуйте онлайн!
Требуется
-XDataKinds
,-XPolyKinds
,-XTypeOperators
,-XUndecidableInstances
, и-XTypeFamilies
.Огромное спасибо Орджану Йохансену, который понял, что создание инфиксного конструктора натуральных чисел и построение аргументов немного по-другому сэкономили два байта, оставив достаточно места для еще одной итерации
#
.Очевидно, что средство проверки типов перестанет пытаться проверить эту программу. Чтобы получить общее представление о том, как будет выглядеть подпись (если она достаточно мала, чтобы поместиться в наблюдаемую вселенную), попробуйте гораздо меньшую
объяснение
СемействоA
#
типов тесно связано с функцией Аккермана – Петера , обычно пишется как , но растет значительно быстрее. Определена функция Аккермана – Петера#
#
с другой стороны, мы можем позвонить и написатьТолько второй случай отличается. Доказательство завершения идентично стандартному для , и должно быть ясно, что для всех и .A B ( m , n ) ≥ A ( m , n ) м N
Здесь мы вычисляем унарное представление
По прямому расчету , т.B ( B ( B ( B ( 0 , 0 ) , 0 ) , 0 ) , 0 ) = 220
Обратите внимание, что - только , поэтому мы неплохо поднялись, чтобы начать. У меня нет четкого представления о том, насколько быстрее растет чем , но, учитывая ход вычислений, похоже, что он будет расти гораздо быстрее.A ( A ( A ( A ( 0 , 0 ) , 0 ) , 0 ) , 0 ) 5 В A
Количество цифр в четном слишком велико, чтобы выразить его практически в десятичном виде, так что это ... довольно смехотворно большое.А ( 6 , 0 )
Определение натуральных чисел
(?)
немного нестандартно. Для экономии места мы используем(?)
как натуральный тип числа (на уровне типа), так и тип прокси (на уровне термина).Я считаю, что либо
TypeFamilies
или (более многословно и запутанно)FunctionalDependencies
необходимо, чтобы получить вычисления на уровне типов, необходимые для достижения действительно больших типов.UndecidableInstances
необходимо обойти очень примитивную проверку завершения Haskell. Другие расширения нужны только для сжатия кода в небольшое доступное пространство.источник
#Z
Z
спереди, чем начинатьS(S Z)#S Z
, или то же самое?#Z
в конце приветствуется.?
сохраняет другой, оставляя место для дополнительного#Z
.A(m,1)
никогда не был большеA(A(m,0),0)
, и собирался сделать замечание, но тогда вы просто оптимизировали до такой степени, что варианты были равны. (Такжеm+1
никогда не бывает большеA(m,0)
.)Haskell, 9 · 2 663552 - 3 (≈ 1,02 · 10 199750 )
Небольшое («маленькое») улучшение по сравнению с xnor's 5⋅2 262144 + 5 . Это 99 байтов.
Как это работает
У нас есть
и так далее, длина которых примерно удваивается для каждого
(:)
. Данное выражениеo.o.o
отработано(:).(:).(:).….(:)
с 2 · 4 6 · 3 4 = 663552 копий(:)
.Haskell с
FlexibleContexts
иNoMonomorphismRestriction
, (200 · 4 331776 + 75 · 331776 + 16) / 9 ≈ 2,53 · 10 199750Небольшое улучшение по сравнению с Bubbler 12 · 2 663552 + 9 · 663552 - 4 ≈ 1,36 · 10 199750 , которое также опирается на эти расширения. Формулировка вызова предполагает, что можно полагаться на них («Например,
Num [a]
иEq [a]
разрешено, даже без определенного экземпляра»); Я не уверен. Это 100 байт.Как это работает
У нас есть
и так далее, с длиной примерно в четыре раза для каждого
(/).(:)
. Данное выражение-o.o.o
работает-(/).(:).(/).(:).….(/).(:)
с 4 6 · 3 4 = 331776 копий(/).(:)
.источник
Haskell, 12 · 2 663552 + 9 · 663552 - 4
Еще одно небольшое улучшение по сравнению с ответом Андерса Касерга .
Как это работает
Только что изменили состав функции
(.)
на дробное деление(/)
.Fractional x
Часть в функции подписи взрывается вместе с основной частью, давая немного более высокий постоянный множитель.источник
С, 979
f
имеет подпись:источник
C ++ 11, неконкурентный
Я едва могу получить это меньше 100 байт, но это настолько близко, что я решил, что мог бы опубликовать это в любом случае, в надежде, что кто-то заметит оптимизацию.
Это пролог стоимостью 93 байта:
И выражение, 9 байтов:
Проиллюстрировать:
Приблизительно удваивается каждый раз, когда число увеличивается.
источник
class
вместо этого использовалось ключевое словоtypename
. Интересно, есть ли где-нибудь компилятор, который все еще поддерживает эту фразу для обратной совместимости?C #, 363
Выражение:
Тип подписи:
Попробуйте онлайн!
источник
Go 1.0 без
reflect
, 98Типы Go 1.x определены статически. Вот моя первая попытка:
На игровой площадке Go :
Перейти 1.9 с использованием псевдонимов типа, 2389
На игровой площадке Go :
Результат:
Go 1 с помощью
reflect
65532В пакете есть ограничение
reflect
на длину имен типов:len(name) <= 1<<16-1
Мне удалось достичь имени типа 65532 байта с этим блоком:
Полный код на игровой площадке Go :
Примечания:
x:=
никогда не считается.источник
reflect
импорт должен быть посчитанИдрис,> гипер (гипер (гипер (гипер (гипер (999999999, 99, 99), 99,99), 99,99), 99,99)
Объяснение:
Мы определяем функцию f, вычисляя тип f (0) - это просто тип модуля, в то время как f (S (n)) вычисляет тип равенства, примененный к аргументу функции, «раздутому» сам по себе, и к f, примененному к n , Последняя строка в основном представляет собой функцию, ожидающую значение типа (27 = (4 = (2 = (1 = ()))))) (для n = 4).
Простой пример
источник
:Type
?hyper
; могли бы вы объяснить?hyper
выражается значительно сильнее, чем остальные, я думаю, вы хотите, чтобы все / большинство из них99
были9
s. (3) Если предположить, что$
работы Идриса, такие как у Хаскелла, внешний набор скобок послеf$
является излишним. (4) Не могли бы вы сократитьhyper
или это потребует подписи типа?Хаскелл, 782
Выражение:
Тип подписи:
источник
sum
тогда(Num a, Foldable t) => t a -> a
Цейлон, 38843546786070481 (~ 4 · 10 16 )
Это 49 вложенных одн кортежей, с пустым кортежем внутри. Краткое имя этого типа фактически совпадает со значением в этом случае, но полностью развернутое имя намного длиннее.
Цейлонный компилятор работает вечно, пытаясь скомпилировать это (компилятор все еще работал через 180 минут) - мне придется попытаться вычислить теоретическую длину типа.
Проблема здесь состоит в том, что тип с одним элементом-кортежем
[X]
фактически представлен в системе типов Цейлона какTuple<X, X, []>
(первый параметр - супертип для всех типов элементов, второй - тип первого элемента, и третий - тип всех, кроме первых элементов , который является здесь пустым кортежем (empty
объект, единственный экземпляр, удовлетворяющий интерфейсуEmpty
)).Так
[]
естьempty
,[[]]
естьTuple<[], [], []>
=Tuple<empty, empty, empty>
,[[[]]]
естьTuple<[[]], [[]], []>
=Tuple<Tuple<[], [], []>, Tuple<[], [], []>, []>
. И полное имя включает в себя имена пакетов, поэтому мы имеем на самом делеceylon.language::Tuple<ceylon.language::Tuple<ceylon.language::empty, ceylon.language::empty, ceylon.language::empty>, ceylon.language::Tuple<ceylon.language::empty, ceylon.language::empty, ceylon.language::empty>, ceylon.language::empty>
всего три уровня. И мы хотим перейти на 50.Поскольку
ceylon.language::empty
длина составляет 22 символа, и каждыйceylon.language::Tuple<?,?,ceylon.language::empty>
добавляет 47 к удвоенному результату предыдущего шага, мы получаемf(1) = 22
, иf(n) = 2 · f(n-1) + 47
. Это упрощаетf(n) = 69 · 2^(n - 1) - 47
, и ввод 50 дает нам 38843546786070481. Конечно, это намного больше, чем то, что уместилось бы в памяти моего компьютера (8 · 10 9 байт).Конечно, компилятор может быть умным и не пытаться хранить полное имя типа в памяти, пока не будет запрошено его имя.
Вот полная программа, пытающаяся напечатать тип:
источник
C # (интерактивный компилятор Visual C #) , 99 байт, оценка 841
Попробуйте онлайн!
Выходы
источник