Головоломка
Маленькая головоломка, которую я услышал, когда учился в старшей школе, выглядела примерно так ...
- Спрашивающий просил меня дать ему номер;
- Услышав число, вопрошающий неоднократно производил на нем некую трансформацию (например, он мог сказать, что десять - это три ), пока, в конце концов, не достигал числа 4 (в этот момент он закончил с четырьмя - это магия ).
- Кажется, что любое число в конце концов превратится в четыре, несмотря ни на что.
Цель состояла в том, чтобы попытаться вычислить функцию трансформации, а затем самому надежно проанализировать эту головоломку.
Решение
Функция преобразования на любом этапе заключалась в том, чтобы
- Возьмите номер, о котором идет речь,
- Подсчитайте количество букв в его представлении английского слова, игнорируя дефис, пробелы или «и» (например, «десять» состоит из 3 букв, «тридцать четыре» - из 10 букв, «сто сорок три». в нем 20 букв).
- Верните это количество букв.
Для всех чисел, которые мне когда-либо приходилось проверять, это сходится к 4. Поскольку «четыре» также содержит четыре буквы, здесь будет бесконечный цикл; вместо этого по соглашению это просто называется магией завершения последовательности.
Соревнование
Ваша задача состоит в том, чтобы создать фрагмент кода, который будет считывать число от пользователя, а затем печатать строки, показывающие многократно применяемую функцию преобразования, пока не будет достигнуто выражение «четыре - это волшебство».
В частности:
- Решения должны быть законченными программами сами по себе. Они не могут быть просто функциями, которые принимают на вход числовой фактор.
- Ввод должен быть прочитан из стандартного ввода. (Канал из "echo" или использование перенаправления ввода нормально, поскольку это также идет из стандартного ввода)
- Ввод должен быть в числовой форме.
- Для каждого применения функции преобразования должна быть напечатана строка:,
a is b.
где a и b - числовые формы чисел в преобразовании. - Точки (точки) ОБЯЗАТЕЛЬНЫ!
- Последняя строка должна естественно сказать,
4 is magic.
. - Код должен выдавать правильный вывод для всех чисел от 0 до 99 .
Примеры:
> 4
4 is magic.
> 12
12 is 6.
6 is 3.
3 is 5.
5 is 4.
4 is magic.
> 42
42 is 8.
8 is 5.
5 is 4.
4 is magic.
> 0
0 is 4.
4 is magic.
> 99
99 is 10.
10 is 3.
3 is 5.
5 is 4.
4 is magic.
Победителем становится самая короткая заявка по количеству символов в исходном коде, что тоже верно .
БОНУС
Вы также можете попробовать написать версию кода, которая выводит АНГЛИЙСКИЕ ИМЕНА для чисел при каждом применении функции преобразования. Исходный ввод по-прежнему числовой, но строки вывода должны иметь форму слова числа.
(Двойной бонус за рисование фигур вашим кодом)
(РЕДАКТИРОВАТЬ) Некоторые пояснения:
- Я хочу, чтобы слово появлялось с обеих сторон во всех применимых случаях, например
Nine is four. Four is magic.
- Однако меня не волнует капитализация. И меня не волнует, как вы разделяете токены слова, хотя они должны быть разделены:
ninety-nine
хорошо,ninety nine
хорошо,ninetynine
не хорошо.
Я рассматриваю их как отдельную категорию для бонусных соревнований в отношении задачи, поэтому, если вы пойдете на это, не беспокойтесь о том, что ваш код будет длиннее, чем числовая версия.
Не стесняйтесь отправлять по одному решению для каждой версии.
источник
Ответы:
GolfScript -
10196939291909486 байт90 → 94
: Фиксированный вывод для кратных 1094 → 86
.: реструктурированный код. Использование базы 100 для удаления непечатаемых символов.86 → 85
: Более короткое преобразование в строку.источник
"magic."
, это в значительной степени подводит итог.d
Извлекается с помощью)
as100
и используется как основание для преобразования базы.Perl, около 147 символов
Свободно основано на решении Platinum Azure:
источник
pop
без каких-либо аргументов. Вне подпрограммыpop
удаляет и возвращает последнее значение,@ARGV
которое является списком аргументов программы Perl. Его так же легко можно было бы заменитьshift
, но это добавит еще 2 символа. См .: p3rl.org/pop'.'
, который равен 2\n
или 1, если вы считаете пробелы в'. '
(пробел является литералом новой строки)Common Lisp 157 символов
Новая, более соответствующая версия, теперь читающая стандартную форму ввода и игнорирующая пробелы и дефисы:
В удобочитаемой форме:
И несколько тестовых прогонов:
И бонусная версия на 165 символов:
Давать
источник
Python 2.x, 144
150154166символыЭто разделит число на десятки и единицы и просуммирует их. Здесь злоупотребляют нежелательным свойством псевдотроичного оператора,
a and b or c
которыйc
возвращается, если онb
равен 0.Предыдущая наивная версия (150 символов). Просто закодируйте все длины как целое число.
источник
n,"is",p,"."
? Я думаю, что вы все еще сохраняете некоторые персонажи, если я считаю правильно).
.int()
, скажем, чего-то из модулейstruct
илиbase64
...C - с числовыми словами
445431427421399386371359 *356354 †348347 символовВот и все. Я не думаю, что смогу сделать это короче.
Все символы новой строки предназначены для удобства чтения и могут быть удалены:
i;P(x){char*p=",one,two,three,four,five,six,sM,eight,nine,tL,elM,twelve,NP,4P, fifP,6P,7P,8O,9P,twLQ,NQ,forQ,fifQ,6Q,7Q,8y,9Q,en,evL,thir,eL,tO,ty, is ,.\n, 4RmagicS,zero,";while(x--)if(*++p-44&&!x++)*p>95|*p<48?putchar(*p),++i:P(*p-48); }main(c){for(scanf("%d",&c);c+(i=-4);P(34),P(c=i),P(35))P(c?c>19?P(c/10+18), (c%=10)&&putchar(45):0,c:37);P(36);}
Ниже он несколько не уточнен, но все еще довольно труден для чтения. См. Ниже более читаемую версию.
i; P(x){ char*p=",one,two,three,four,five,six,sM,eight,nine,tL,elM,twelve,NP,4P,fifP,6P,7P,8O,9P,twLQ,NQ,forQ,fifQ,6Q,7Q,8y,9Q,en,evL,thir,eL,tO,ty, is ,.\n,4RmagicS,zero,"; while(x--) if(*++p-44&&!x++) *p>95|*p<48?putchar(*p),++i:P(*p-48); } main(c){ for(scanf("%d",&c);c+(i=-4);P(34),P(c=i),P(35)) P(c? c>19? P(c/10+18), (c%=10)&& putchar(45) :0, c :37); P(36); }
Развернуто и прокомментировано:
int count; /* type int is assumed in the minified version */ void print(int index){ /* the minified version assumes a return type of int, but it's ignored */ /* see explanation of this string after code */ char *word = /* 1 - 9 */ ",one,two,three,four,five,six,sM,eight,nine," /* 10 - 19 */ "tL,elM,twelve,NP,4P,fifP,6P,7P,8O,9P," /* 20 - 90, by tens */ "twLQ,NQ,forQ,fifQ,6Q,7Q,8y,9Q," /* lookup table */ "en,evL,thir,eL,tO,ty, is ,.\n,4RmagicS,zero,"; while(index >= 0){ if(*word == ',') index--; else if(index == 0) /* we found the right word */ if(*word >= '0' && *word < 'a') /* a compression marker */ print(*word - '0'/*convert to a number*/); else{ putchar(*word); /* write the letter to the output */ ++count; } ++word; } } int main(int argc, char **argv){ /* see note about this after code */ scanf("%d", &argc); /* parse user input to an integer */ while(argc != 4){ count = 0; if(argc == 0) print(37/*index of "zero"*/); else{ if(argc > 19){ print(argc / 10/*high digit*/ + 20/*offset of "twenty"*/ - 2/*20 / 10*/); argc %= 10; /* get low digit */ if(argc != 0) /* we need a hyphen before the low digit */ putchar('-'); } print(argc/* if 0, then nothing is printed or counted */); } argc = count; print(34/*" is "*/); print(argc); /* print count as word */ print(35/*".\n"*/); } print(36/*"four is magic.\n"*/); }
О закодированной строке в начале
Названия номеров сжаты по очень простой схеме. Часто используемые подстроки заменяются односимвольными индексами в массив имен. «Таблица поиска» дополнительных записей имен добавляется в конец для подстрок, которые не используются полностью в первом наборе. Поиски рекурсивны: записи могут ссылаться на другие записи.
Например, сжатое имя для 11 -
elM
.print()
Функция выводит символыe
иl
( в нижнем регистре «L», а не номер «1») дословно, но тогда он находитM
, поэтому он называет себя с индексом записи 29 (ASCII «М» - ASCII «0») в поисковую таблицу. Это строкаevL
, поэтому она выводитe
иv
, затем снова вызывает себя с индексом 28-й записи в таблице поиска, то естьen
, и выводится дословно. Это полезно, потому чтоen
также используется вeL
foreen
(используется послеeight
ineighteen
), которое используется вtO
forteen
(используется для любого другого-teen
имени).Эта схема приводит к довольно значительному сжатию имен чисел, при этом требуется лишь небольшой объем кода для распаковки.
Запятые в начале и в конце строки объясняют упрощенный способ нахождения подстрок в этой строке. Добавление двух символов сюда позволяет сохранить больше символов позже.
О злоупотреблении
main()
argv
игнорируется (и, следовательно, не объявляется в сжатой версии), значение argc игнорируется, но хранилище повторно используется для хранения текущего числа. Это просто избавляет меня от необходимости объявлять дополнительную переменную.Об отсутствии
#include
Некоторые будут жаловаться, что пропуск
#include <stdio.h>
- это обман. Это совсем не так. Это полностью легальная программа на C, которая будет правильно компилироваться на любом компиляторе C, который я знаю (хотя и с предупреждениями). Не имея прототипов для функций stdio, компилятор будет считать, что они возвращают функции cdeclint
, и будет полагать, что вы знаете, какие аргументы передать. В любом случае возвращаемые значения игнорируются в этой программе, и все они являются функциями cdecl (соглашение о вызовах "C"), и мы действительно знаем, какие аргументы передать.Выход
Результат ожидаемый:
* Предыдущая версия не учитывала две части спецификации: она не обрабатывала ноль и вводила данные в командной строке вместо стандартного ввода. Обработка нулей добавленных символов, но использование stdin вместо аргументов командной строки, а также пара других оптимизаций позволили сохранить то же количество символов, что привело к размывке.
† Требования были изменены, чтобы прояснить, что числовое слово должно быть напечатано с обеих сторон от «есть». Эта новая версия соответствует этому требованию и реализует еще пару оптимизаций для (более чем) учета необходимого дополнительного размера.
источник
J, 107
112знаков(Новая строка только для удобства чтения)
Использование и вывод:
источник
T-SQL, 413
451499символов(Не то чтобы я серьезно предлагал вам это сделать ... на самом деле я просто хотел написать CTE)
Использовать:
Возврат
источник
CREATE FUNCTION d(@ int) RETURNS int AS BEGIN Declare @l char(9),@s char(50) Select @l='066555766',@s='03354435543668877987' if @=0 return 4 if @<20 return 0+substring(@s,@+1,1)return 0+substring(@l,@/10,1)+substring(@s,@%10+1,1)END
Java (с шаблонным),
308290286282280 символовЯ уверен, что Groovy избавится от большей части этого.
Объяснение и форматирование (все комментарии, новые строки и начальные / конечные пробелы удалены в счетчике):
Достаточно прямолинейно, но
Изменить: больше не использовать шестигранник, это меньше нажатий клавиш
источник
String[]a
вместоString[] a
.Windows PowerShell: 152
153184байтана основе предыдущего решения, с большим влиянием других решений
источник
$input
должны оставаться, так как вы не можете напрямую привести перечислительint
; это работает при прохожденииstring
сначала :-)C, 158 знаков
(Первоначально основанный на коде Python Влада, позаимствован трюк из решения C ++ Тома Сиргедаса, чтобы выжать еще несколько символов)
расширенная версия:
источник
Питон, 129
133137148символыВ качестве разминки вот моя первая версия (улучшенная на пару символов по сравнению с предыдущим лучшим Python).
PS. После нескольких редакций теперь он примерно на двадцать символов короче:
источник
C #: 210 символов.
Squished:
Расширенный:
Уловки, которые использует этот подход:
Console.
доC.
?:
) вместоif/else
.\n
сWrite
кодом вместоWriteLine
Write
вызова функцииисточник
int[] z
будет короче, так как он не нуждается вnew[]
"magic"
чтобыobject
, было бы неявно называтьToString()
наy
добавлением""
. Но, поскольку+
имеет более высокий приоритет , чем?:
, вы должны положить его в истинной части вместо ложной части:x!=4?y+"":"magic"
.Perl: 148 символов
(Perl:
233181212206200199198185179149148 символов)r
не нужно, еще немного сбрили.Давайте начнем с этого, сделав скромную попытку в Perl.
Ухищрения:
Слишком много!
источник
@u=split$x,'43350435543668877988';
ваши запятые используют ненужные 19 символов, разбиваясь наundef
разделители на каждом$x
символе , я использую как неопределенную переменную вместо undef - всего экономия: 11 знаков. Кроме того , удалитеm
вchomp
и вы получите еще один персонаж сбрил ваш счет.sub r
полностью проигрывая - вы используете его только один раз, и вы можете заменить все это одним вложенным троичным без даже парных скобок. Моя версия - 144 символа прямо сейчас: gist.github.com/473289JavaScript 1.8 (SpiderMonkey) - 153 символа
Применение:
echo 42 | js golf.js
Выход:
С бонусом - 364 символа
Выход:
источник
Haskell, 224
270символовИ немного читабельнее -
источник
Версия C ++ Stdio, уменьшенная: 196 символов
Версия C ++ Iostreams, уменьшенная: 195 символов
Исходный, без минификации: 344 символа
источник
#define
он будет еще короче, так как может заменить несколько жетонов.printf("is magic".\n)
=>puts
.printf("%d",p)
=>puts(atoi(p))
. Не только короче, но и быстрее.while(p!=4)
можно было бы сократить доwhile(p-4)
. Один цельный персонаж, я знаю, но все же. :-)Delphi: 329 символов
Однострочная версия:
Отформатирован:
Наверное, хватит еще немного ... :-P
источник
C #
314286283274289273252 символа.Squished:
Обычный:
Edit Dykam: сделал довольно осторожные вставки и изменения:
object
изstring
"magic"
.o
, чтобы я мог переместить заbreak
пределыfor
цикла, то есть в результатеdo-while
.o
присваивание, а такжеv
присваивание, продолжая вставлять вычислениеl
в аргументы функции в целом, устраняя необходимость вl
. Также встроено назначениеm
.int[] x
,int[]x
тоже допустимо.using System.Linq
было слишком много, чтобы сделать это улучшением.Edit 2 Dykam Изменен массив int на массив / строку char, добавлена правильная арифмика, чтобы исправить это.
источник
Lua, 176 символов
или
источник
C - без числовых слов
180175*172167 символовВсе символы новой строки предназначены для удобства чтения и могут быть удалены:
i;V(x){return"\3#,#6$:WOXB79B"[x/2]/(x%2?1:10)%10;}main(c){for(scanf("%d",&c); c-4;)i=c,printf("%d is %d.\n",i,c=c?c>19?V(c/10+19)+V(c%10):V(c):4);puts( "4 is magic.");}
Немного не минифицированный:
i; V(x){return"\3#,#6$:WOXB79B"[x/2]/(x%2?1:10)%10;} main(c){ for(scanf("%d",&c);c-4;) i=c, printf("%d is %d.\n",i,c=c?c>19?V(c/10+19)+V(c%10):V(c):4); puts("4 is magic."); }
* Предыдущая версия не учитывала две части спецификации: она не обрабатывала ноль и вводила данные в командной строке вместо стандартного ввода. Обработка нулевых добавленных символов, но использование stdin вместо аргументов командной строки сэкономило еще больше, что привело к чистой экономии.
источник
perl,
123122символаПросто понял, что нет необходимости выводить в STDOUT, поэтому вместо этого выведите в STDERR и отбросьте другой символ.
И версия, которая возвращает прописанные числа:
279278276280 знаковХотя это соответствует спецификации, он не на 100% хорошо отформатирован. Он возвращает дополнительный пробел после чисел, заканчивающихся нулем. В спецификации говорится:
Хотя это вроде как ласково. Более правильная версия на
282281279283 знаковисточник
Python:
источник
N = input()
(илиraw_input()
) и удалитьsys
материал.she-bang
в ответе на код-гольф ;-)C ++, 171 символ (#include опущено)
источник
#include
потому что функции будут просто приниматьint
параметры. Вы даже можете сохранить удар, сделавmain
возвратint
.Рубин, 164 символа
расшифровано:
источник
Lua
185190199добавлены точки, добавлены io.read, удалены () при последней печати
с переносом строки
источник
n=io.read()
(+11 символов) для соответствия правилу чтения числа со стандартного ввода. Изменениеprint('4 is magic.')
наprint'4 is magic.'
сэкономит 2 символа. Удаление;
после)
сохранит 1 символ. Вprint
использовании запятых , кажется , как обман, но спекуляция неясно. Можно также изменить его на,print(n,'is',m,'.')
чтобы сохранить 2 символа.Код PhP
//////////// тестирование ////////////////
////// Полученные результаты /////////
источник
$l='4335443554366887798866555766';for($b=(int)fgets(fopen('php://stdin','r'));($a=$b)-4;){$b=$a<20?$l[$a]:$l[18+$a/10]+($a%10?$l[$a%10]:0);echo"$a is $b.\n";}echo"4 is magic.\n";
Perl - 130 символов
5.12.1 (130 символов)
1211231321361405.10.1 (134 символа)
125127136140144История изменений:
20100714:2223
- отменил изменение до сведения мобрула , но($_%10&&$u[$_%10])
→(($_%=10)&&$u[$_])
, что такое же количество символов, но я сделал это на случай, если кто-то увидит способ его улучшить20100714:0041
-split//,'...'
→'...'=~/./g
20100714:0025
-($_%10&&$u[$_%10])
→$u[$_%10]
20100713:2340
-while$_
→until/\D/
+ удалены ненужные скобки20100713:xxxx
-$=<>;chop;
→$_=pop;
- любезно предоставлено mobruleПримечание: я устал улучшать ответы других в комментариях, поэтому теперь я жадный и могу просто добавить свои изменения здесь :) Это отделено от ответа Platinum Azure - частично заслуга Хоббса , mobrule и Платиновая лазурь .
источник
$_%10&&...
конструкции, вы нарушили спецификацию для входов 20,30,40, ...ARGV
, которое заполняетсяSTDIN
:) или ..echo bar | xargs perl foo.pl
, технически передано из echo в аргументы для perl :)Shameless Perl с числовыми словами (329 символов)
Адаптировано непосредственно из кода P Daddy на C, с некоторыми настройками, чтобы
p()
заставить его делать то же самое, используя примитивы Perl вместо примитивов C, и в основном переписанный основной цикл. См. Его для объяснения. Новые строки необязательны.Боковое примечание: очень плохо, что perl
print
просто возвращает true / false; если бы он вернул счет, это спасло бы меня 7 ударов.источник
Рубин, 141 символ:
источник
источник