Код Гольф: Четыре - это волшебство

88

Головоломка

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

  • Спрашивающий просил меня дать ему номер;
  • Услышав число, вопрошающий неоднократно производил на нем некую трансформацию (например, он мог сказать, что десять - это три ), пока, в конце концов, не достигал числа 4 (в этот момент он закончил с четырьмя - это магия ).
  • Кажется, что любое число в конце концов превратится в четыре, несмотря ни на что.

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

Решение

Функция преобразования на любом этапе заключалась в том, чтобы

  • Возьмите номер, о котором идет речь,
  • Подсчитайте количество букв в его представлении английского слова, игнорируя дефис, пробелы или «и» (например, «десять» состоит из 3 букв, «тридцать четыре» - из 10 букв, «сто сорок три». в нем 20 букв).
  • Верните это количество букв.

Для всех чисел, которые мне когда-либо приходилось проверять, это сходится к 4. Поскольку «четыре» также содержит четыре буквы, здесь будет бесконечный цикл; вместо этого по соглашению это просто называется магией завершения последовательности.

Соревнование

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

В частности:

  1. Решения должны быть законченными программами сами по себе. Они не могут быть просто функциями, которые принимают на вход числовой фактор.
  2. Ввод должен быть прочитан из стандартного ввода. (Канал из "echo" или использование перенаправления ввода нормально, поскольку это также идет из стандартного ввода)
  3. Ввод должен быть в числовой форме.
  4. Для каждого применения функции преобразования должна быть напечатана строка:, a is b.где a и b - числовые формы чисел в преобразовании.
  5. Точки (точки) ОБЯЗАТЕЛЬНЫ!
  6. Последняя строка должна естественно сказать, 4 is magic..
  7. Код должен выдавать правильный вывод для всех чисел от 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.

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

БОНУС

Вы также можете попробовать написать версию кода, которая выводит АНГЛИЙСКИЕ ИМЕНА для чисел при каждом применении функции преобразования. Исходный ввод по-прежнему числовой, но строки вывода должны иметь форму слова числа.

(Двойной бонус за рисование фигур вашим кодом)

(РЕДАКТИРОВАТЬ) Некоторые пояснения:

  1. Я хочу, чтобы слово появлялось с обеих сторон во всех применимых случаях, например Nine is four. Four is magic.
  2. Однако меня не волнует капитализация. И меня не волнует, как вы разделяете токены слова, хотя они должны быть разделены: ninety-nineхорошо, ninety nineхорошо, ninetynineне хорошо.

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

Не стесняйтесь отправлять по одному решению для каждой версии.

Platinum Azure
источник
1
Какое количество мы должны обработать? <100? <1000? <1000000? <2 ** 31?
P Daddy
1
Поскольку здесь нужно всего лишь перейти от 0 до 99, я подозреваю, что быстрое и короткое решение будет заключаться в жестком кодировании значений, которым сопоставляются 0-99, а затем в цикле до тех пор, пока вы не дойдете до 4. После этого начинается микронастройка.
Beska
@P Папа ... часть 6 говорит только 0-99.
Beska
14
4 - это всего лишь магия, потому что она была выбрана честным броском кубиков.
VirtuosiMedia

Ответы:

57

GolfScript - 101 96 93 92 91 90 94 86 байт

90 → 94: Фиксированный вывод для кратных 10
94 → 86.: реструктурированный код. Использование базы 100 для удаления непечатаемых символов.
86 → 85: Более короткое преобразование в строку.

{n+~."+#,#6$DWOXB79Bd")base`1/10/~{~2${~1$+}%(;+~}%++=" is "\".
"1$4$4-}do;;;"magic."
набб
источник
почему это так далеко? он короче, чем lisp, и не использует встроенную функцию форматирования
Claudiu
36
Мне нравится, чем заканчивается код "magic.", это в значительной степени подводит итог.
Aistina
@Aistina: Думаю, это легко сделать в этой задаче. :-)
Platinum Azure
9
@Aistina: ха-ха, это забавно. "mumbo jumbo yada yada..magic"
vol7ron
1
@P Daddy dИзвлекается с помощью )as 100и используется как основание для преобразования базы.
Набб
85

Perl, около 147 символов

Свободно основано на решении Platinum Azure:

               chop
              ($_.=
              <>);@
             u="433
            5443554
           366  887
          798   866
         555    766
        "=~     /\d
       /gx      ;#4
      sub       r{4
     -$_        ?$_
    <20         ?$u
   [$_          ]:(
  $'?           $u[
 $']            :0)
+$u[18+$&]:magic}print"
$_ is ",$_=r(),'.'while
                /\d
                /x;
                444
моб
источник
1
@Platinum Azure способ получения входных данных - использование popбез каких-либо аргументов. Вне подпрограммы popудаляет и возвращает последнее значение, @ARGVкоторое является списком аргументов программы Perl. Его так же легко можно было бы заменить shift, но это добавит еще 2 символа. См .: p3rl.org/pop
Брэд Гилберт,
похоже, что вам нужен символ новой строки '.', который равен 2 \nили 1, если вы считаете пробелы в '. '(пробел является литералом новой строки)
vol7ron
Немного длиннее, но творчество в моей книге имеет большое значение.
Beska
@Platinum Azure и др.: Он получает информацию от стандартного ввода. Это способ сделать это в Perl. (Может, он изменил это после вашего комментария?)
Фрэнк
@P Daddy: стон, но все равно +1 к твоему комментарию
Platinum Azure
30

Common Lisp 157 символов

Новая, более соответствующая версия, теперь читающая стандартную форму ввода и игнорирующая пробелы и дефисы:

(labels((g (x)(if(= x 4)(princ"4 is magic.")(let((n(length(remove-if(lambda(x)(find x" -"))(format nil"~r"x)))))(format t"~a is ~a.~%"x n)(g n)))))(g(read)))

В удобочитаемой форме:

 (labels ((g (x)
           (if (= x 4)
            (princ "4 is magic.")
            (let ((n (length (remove-if (lambda(x) (find x " -"))
                                        (format nil "~r" x)))))
               (format t"~a is ~a.~%" x n)
               (g n)))))
    (g (read)))

И несколько тестовых прогонов:

>24
24 is 10.
10 is 3.
3 is 5.
5 is 4.
4 is magic.

>23152436
23152436 is 64.
64 is 9.
9 is 4.
4 is magic.

И бонусная версия на 165 символов:

 (labels((g(x)(if(= x 4)(princ"four is magic.")(let*((f(format nil"~r"x))(n(length(remove-if(lambda(x)(find x" -"))f))))(format t"~a is ~r.~%"f n)(g n)))))(g(read)))

Давать

>24
twenty-four is ten.
ten is three.
three is five.
five is four.
four is magic.

>234235
two hundred thirty-four thousand two hundred thirty-five is forty-eight.
forty-eight is ten.
ten is three.
three is five.
five is four.
four is magic.
оборота user110763
источник
5
Я думал, что в «двадцать четыре» всего 10 букв?
kennytm
1
Цифры после "is" тоже должны быть текстом.
Mike DeSimone
5
почему это так высоко? другие не используют встроенную функцию форматирования, и в них меньше символов,
Клаудиу
3
@Claudiu Потому что Common Lisp потрясающий.
Mornedhel
3
Неважно, сколько ударов вы сделаете, если мяч не попал в лунку. Люди, кажется, забывают об этом, когда голосуют за неправильные решения.
Марк Петерс
21

Python 2.x, 144 150 154 166 символы

Это разделит число на десятки и единицы и просуммирует их. Здесь злоупотребляют нежелательным свойством псевдотроичного оператора, a and b or cкоторый cвозвращается, если он bравен 0.

n=input()
x=0x4d2d0f47815890bd2
while n-4:p=n<20and x/10**n%10or 44378/4**(n/10-2)%4+x/10**(n%10)%10+4;print n,"is %d."%p;n=p
print"4 is magic."

Предыдущая наивная версия (150 символов). Просто закодируйте все длины как целое число.

n=input()
while n-4:p=3+int('1yrof7i9b1lsi207bozyzg2m7sclycst0zsczde5oks6zt8pedmnup5omwfx56b29',36)/10**n%10;print n,"is %d."%p;n=p
print"4 is magic."
KennyTM
источник
Извините, я специально хотел точки только из-за таких вещей. :-) Хорошая запись! (РЕДАКТИРОВАТЬ: я не знаю Python, но не могли бы вы n,"is",p,"."? Я думаю, что вы все еще сохраняете некоторые персонажи, если я считаю правильно)
Platinum Azure
2
@Plat: это приведет к появлению лишнего пробела перед ..
kennytm
@KennyTM: О, да, я должен был заметить это даже из отрывка. Ой! Ну, в любом случае, как я уже сказал, некоторые спецификации были специально разработаны, чтобы немного усложнить ситуацию. :-)
Platinum Azure
Можем ли мы сократить его, используя базу выше 36?
MikeD
@MikeD: Нет. Из документации Python: «Параметр base дает основу для преобразования (по умолчанию 10) и может быть любым целым числом в диапазоне [2, 36] или нулем». Теперь вы могли бы использовать другую функцию, кроме int(), скажем, чего-то из модулей structили base64...
Майк Дезимоун,
20

C - с числовыми словами

445 431 427 421 399 386 371 359 * 356 354 348 347 символов

Вот и все. Я не думаю, что смогу сделать это короче.

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

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также используется в eLfor een(используется после eightin eighteen), которое используется в tOfor teen(используется для любого другого -teenимени).

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

Запятые в начале и в конце строки объясняют упрощенный способ нахождения подстрок в этой строке. Добавление двух символов сюда позволяет сохранить больше символов позже.

О злоупотреблении main()

argvигнорируется (и, следовательно, не объявляется в сжатой версии), значение argc игнорируется, но хранилище повторно используется для хранения текущего числа. Это просто избавляет меня от необходимости объявлять дополнительную переменную.

Об отсутствии #include

Некоторые будут жаловаться, что пропуск #include <stdio.h>- это обман. Это совсем не так. Это полностью легальная программа на C, которая будет правильно компилироваться на любом компиляторе C, который я знаю (хотя и с предупреждениями). Не имея прототипов для функций stdio, компилятор будет считать, что они возвращают функции cdecl int, и будет полагать, что вы знаете, какие аргументы передать. В любом случае возвращаемые значения игнорируются в этой программе, и все они являются функциями cdecl (соглашение о вызовах "C"), и мы действительно знаем, какие аргументы передать.

Выход

Результат ожидаемый:

0
ноль - четыре.
четыре - это магия.
1
один - три.
три - пять.
пять - четыре.
четыре - это магия.
4
четыре - это магия.
20
двадцать шесть.
шесть - три.
три - пять.
пять - четыре.
четыре - это магия.
21 год
двадцать один - девять.
девять - четыре.
четыре - это магия.

* Предыдущая версия не учитывала две части спецификации: она не обрабатывала ноль и вводила данные в командной строке вместо стандартного ввода. Обработка нулей добавленных символов, но использование stdin вместо аргументов командной строки, а также пара других оптимизаций позволили сохранить то же количество символов, что привело к размывке.

Требования были изменены, чтобы прояснить, что числовое слово должно быть напечатано с обеих сторон от «есть». Эта новая версия соответствует этому требованию и реализует еще пару оптимизаций для (более чем) учета необходимого дополнительного размера.

P Daddy
источник
Это мой самый любимый ответ на слово ... Браво, молодец. +1 для вас, и если бы я мог поставить две галочки, я бы поставил.
Platinum Azure
5
Это интересно читать, думаю, теперь я буду использовать эти числа в повседневной жизни. Шесть, сем, восемь, девять, тел, элем, двенадцать, энпи, четырепи, фифпи, шестипи, семипи, восьмая, девятипи, двенадцатилетняя ... =)
deceze
10

J, 107 112 знаков

'4 is magic.',~}:('.',~":@{.,' is ',":@{:)"1]2&{.\.
(]{&(#.100 4$,#:3 u:ucp'䌵䐵吶梇禈榛ꪛ멩鮪鮺墊馊꥘誙誩墊馊ꥺ겻곋榛ꪛ멩鮪鮺'))^:a:

(Новая строка только для удобства чтения)

Использование и вывод:

    '4 is magic.',~}:('.',~":@{.,' is ',":@{:)"1]2&{.\.(]{&(#.100 4$,#:3 u:ucp'䌵䐵吶梇禈榛ꪛ멩鮪鮺墊馊꥘誙誩墊馊ꥺ겻곋榛ꪛ멩鮪鮺'))^:a:12
12 is 6.    
6 is 3.     
3 is 5.     
5 is 4.     
4 is magic. 
Давида
источник
15
Он составлен на китайском языке
Д-р Велисарий
3
Пожалуйста, выберите не китайского судью
Доктор Велисарий
3
@beli: 멩, 겻, 곋, 멩 корейцы.
kennytm
1
Моя жена (носитель китайского языка) говорит, что это смесь китайского и корейского языков.
Loren Pechtel
3
@belisarius: 1) Она не знает корейского. 2) Китайцы тарабарщины.
Loren Pechtel
10

T-SQL, 413 451 499 символов

CREATE FUNCTION d(@N int) RETURNS int AS BEGIN
Declare @l char(50), @s char(50)
Select @l='0066555766',@s='03354435543668877987'
if @N<20 return 0+substring(@s,@N+1,1) return 0+substring(@l,(@N/10)+1,1) + 0+(substring(@s,@N%10+1,1))END
GO
CREATE proc M(@x int) as BEGIN
WITH r(p,n)AS(SELECT p=@x,n=dbo.d(@x) UNION ALL SELECT p=n,n=dbo.d(n) FROM r where n<>4)Select p,'is',n,'.' from r print '4 is magic.'END

(Не то чтобы я серьезно предлагал вам это сделать ... на самом деле я просто хотел написать CTE)

Использовать:

M 95

Возврат

p                n
----------- ---- -----------
95          is   10.
10          is   3.
3           is   5.
5           is   4.
4 is magic.
Леон Бамбрик
источник
Разве вы не можете просто распечатать отдельные результаты вместо возврата таблицы? Это сделало бы вывод лучше.
Joey
1
Я не думаю, что он правильно обрабатывает ноль. Как насчет чего-то вроде этого: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
Гейб
9

Java (с шаблонным), 308 290 286 282 280 символов

class A{public static void main(String[]a){int i=4,j=0;for(;;)System.out.printf("%d is %s.%n",i=i==4?new java.util.Scanner(System.in).nextInt():j,i!=4?j="43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:".charAt(i)-48:"magic");}}

Я уверен, что Groovy избавится от большей части этого.

Объяснение и форматирование (все комментарии, новые строки и начальные / конечные пробелы удалены в счетчике):

Достаточно прямолинейно, но

//boilerplate
class A{
   public static void main(String[]a){
      //i is current/left number, j right/next number.  i=4 signals to start
      //by reading input
      int i=4,j=0;
      for(;;)
         //print in the form "<left> is <right>."
         System.out.printf(
            "%d is %s.%n",
            i=i==4?
               //<left>: if i is 4 <left> will be a new starting number
               new java.util.Scanner(System.in).nextInt():
               //otherwise it's the next val
               j,
            i!=4?
               //use string to map number to its length (:;< come after 9 in ASCII)
               //48 is value of '0'.  store in j for next iteration
               j="43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:".charAt(i)-48:
               //i==4 is special case for right; print "magic"
               "magic");
   }
}

Изменить: больше не использовать шестигранник, это меньше нажатий клавиш

Марк Питерс
источник
1
249 без импорта, class def или main def.
Марк Петерс,
1
Это дьявольски. Мне нравится база 16. (+1)
Platinum Azure
Вы можете сэкономить одно место, используя String[]aвместо String[] a.
BalusC
Спасибо @Balus, также устранил кучу, выполнив простую арифметику над символом вместо использования шестнадцатеричного разбора.
Марк Петерс
@Mark Peters: Еще хуже. Я чувствую себя таким ванильным по сравнению с этим.
Platinum Azure
9

Windows PowerShell: 152 153 184 байта

на основе предыдущего решения, с большим влиянием других решений

$o="03354435543668877988"
for($input|sv b;($a=$b)-4){if(!($b=$o[$a])){$b=$o[$a%10]-48+"66555766"[($a-$a%10)/10-2]}$b-=48-4*!$a
"$a is $b."}'4 is magic.'
хорошо
источник
Исправлено для поддержки кратных 10 («девяносто», а не «девяносто ноль»).
Гейб
Привет, @Gabe :), спасибо; в последнее время не так много времени на гольф. Тем не менее, кавычки $inputдолжны оставаться, так как вы не можете напрямую привести перечислитель int; это работает при прохождении stringсначала :-)
Joey
8

C, 158 знаков

main(n,c){char*d="03354435543668877988";for(scanf("%d",&n);n-4;n=c)printf("%d is %d.\n",n,c=n?n<19?d[n]-48:d[n%10]-"_,**+++)**"[n/10]:4);puts("4 is magic.");}

(Первоначально основанный на коде Python Влада, позаимствован трюк из решения C ++ Тома Сиргедаса, чтобы выжать еще несколько символов)

расширенная версия:

main(n, c) {
    char *d = "03354435543668877988";
    for (scanf("%d",&n); n-4; n = c)
        printf("%d is %d.\n", n, c = n ? n<19 ? d[n]-48 : d[n%10] - "_,**+++)**"[n/10]  : 4);
    puts("4 is magic.");
}
Ферруччо
источник
Похоже, у меня не работает: ./magic 10 10 is -27. Ошибка сегментации
Кейси
@Casey - вызов scanf () был немного схематичным. Он читал int в char. Мне это сходило с рук в OSX, а в Windows это работало, но вылетало при выходе. Итак, я снова сделал n & c ints. Я понял, что могу отбросить ключевое слово int, сделав их параметрами, используя нотацию K&R. Результат безопаснее и короче на один символ.
Ferruccio
Вы можете сохранить 3 символа, заменив " 466555766" [n / 10] + d [n% 10] -96 на d [n% 10] - " , +++) " [n / 10]
Том Сиргедас
6

Питон, 129 133 137 148 символы

В качестве разминки вот моя первая версия (улучшенная на пару символов по сравнению с предыдущим лучшим Python).

PS. После нескольких редакций теперь он примерно на двадцать символов короче:

n=input()
while n-4:p=(922148248>>n/10*3&7)+(632179416>>n%10*3&7)+(737280>>n&1)+4*(n<1);print n,'is %d.'%p;n=p
print'4 is magic.'
Нас Банов
источник
6

C #: 210 символов.

Squished:

using C=System.Console;class B{static void Main(){int
x=0,y=int.Parse(C.ReadLine());while(x!=4)C.Write((x=y)+" is {0}.\n",x==4?"magic":""+(y=x==0?4:"03354435543668877988"[x<20?x:x%10]+"0066555766"[x/10]-96));}}

Расширенный:

using C=System.Console;
class B
{
    static void Main()
    {
        int x=0,y=int.Parse(C.ReadLine());
        while(x!=4)
            C.Write((x=y)+" is {0}.\n",
                x==4?
                     "magic":
                     ""+(y= x==0?
                                4:
                                "03354435543668877988"[x<20?x:x%10]+
                                "0066555766"[x/10]-96)
                   );
    }
}

Уловки, которые использует этот подход:

  • Создайте справочную таблицу для длин имени номера на основе цифр, которые появляются в номере.
  • Используйте поиск символьного массива в строке и арифметику char вместо числового массива.
  • Используйте псевдоним имени класса, чтобы сократить Console.доC.
  • Используйте условный (тернарный) оператор ( ?:) вместо if/else.
  • Используйте escape-код \nс Writeкодом вместоWriteLine
  • Используйте тот факт, что C # имеет определенный порядок оценки, чтобы разрешить назначения внутри Writeвызова функции
  • Используйте выражения присваивания, чтобы исключить лишние инструкции и, следовательно, лишние фигурные скобки
Л.Бушкин
источник
int[] zбудет короче, так как он не нуждается вnew[]
Джоуи
Пересмотрено для использования символьной арифметики вместо поиска по массиву.
LBushkin
@ mdm20: Ты прав. У меня была ошибка в таблице поиска. Исправлено сейчас.
LBushkin
Что ж, двенадцатый раз - прелесть: * D
Л.Бушкин
Quicky , чтобы сохранить 5 символов: короче , чем кастинг , "magic"чтобы object, было бы неявно называть ToString()на yдобавлением "". Но, поскольку +имеет более высокий приоритет , чем ?:, вы должны положить его в истинной части вместо ложной части: x!=4?y+"":"magic".
P Daddy
6

Perl: 148 символов

(Perl: 233 181 212 206 200 199 198 185 179 149 148 символов)

  • Хеш исключений перемещен в массив объектов. Это привело к тому, что я смог вырезать множество персонажей :-)
  • mobrule указал на неприятную ошибку. Быстрое исправление добавляет 31 символ, ай!
  • Переработан для нулевого особого случая, сделана и легкая игра в гольф.
  • Прямой доступ к списку для одноразового использования вместо хранения в массиве? Да, черт возьми!
  • СТОЛЬКО ПЕРЕРАБОТКИ только для ОДНОГО чертова персонажа. Это действительно жизнь игрока в гольф. :-(
  • Упс, легко исправить пробелы. 198 сейчас.
  • Отредактировал некоторый избыточный код.
  • Последнее ключевое слово return rне нужно, еще немного сбрили.
  • Массовый рефакторинг по комментариям; К сожалению, я смог получить его только на 149, потому что мне пришлось исправить ошибку, которая присутствовала как в моем предыдущем коде, так и в версиях комментаторов.
  • Пробуем без слов "магия".

Давайте начнем с этого, сделав скромную попытку в Perl.

@u=split'','4335443554366887798866555766';$_=<>;chop;print"$_ is ".($_=$_==4?0:$_<20?$u[$_]:($u[$_/10+18]+($_%10&&$u[$_%10]))or magic).".
"while$_

Ухищрения:

Слишком много!

Platinum Azure
источник
ACK! Как я никогда не тестировал этого, я никогда не узнаю.
Platinum Azure
У вас там мертвый код? Я не понимаю, как нужен особый случай для нуля, когда $ u [0] равно 4. У меня есть, казалось бы, работающая версия вашего кода с @ 166 символов, и я думаю, что она может быть немного короче.
hobbs
@hobbs: Хороший вопрос, я посмотрю еще раз. История такова, что я прошел половину пути через пару исправлений, и внезапно все сломалось (примерно в той точке, где я выбрал 4 -> 0). Я думаю, что вы правы в этом вопросе :-)
Platinum Azure
Я не считаю себя великим программистом на Perl, но вы можете сократить количество символов: @u=split$x,'43350435543668877988';ваши запятые используют ненужные 19 символов, разбиваясь на undefразделители на каждом $xсимволе , я использую как неопределенную переменную вместо undef - всего экономия: 11 знаков. Кроме того , удалите mв chompи вы получите еще один персонаж сбрил ваш счет.
vol7ron
Делает лучше, но вы все равно можете сэкономить больше, sub rполностью проигрывая - вы используете его только один раз, и вы можете заменить все это одним вложенным троичным без даже парных скобок. Моя версия - 144 символа прямо сейчас: gist.github.com/473289
hobbs
5

JavaScript 1.8 (SpiderMonkey) - 153 символа

l='4335443554366887798866555766'.split('')
for(b=readline();(a=+b)-4;print(a,'is '+b+'.'))b=a<20?l[a]:+l[18+a/10|0]+(a%10&&+l[a%10])
print('4 is magic.')

Применение: echo 42 | js golf.js

Выход:

42 is 8.
8 is 5.
5 is 4.
4 is magic.

С бонусом - 364 символа

l='zero one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty thirty fourty fifty sixty seventy eighty ninety'.split(' ')
z=function(a)a<20?l[a]:l[18+a/10|0]+(a%10?' '+l[a%10]:'')
for(b=+readline();(a=b)-4;print(z(a),'is '+z(b)+'.'))b=z(a).replace(' ','').length
print('four is magic.')

Выход:

девяносто девять - десять.
десять - три.
три - пять.
пять - четыре.
четыре - это магия.
оборота gnarf
источник
4

Haskell, 224 270 символов

o="43354435543668877988"
x!i=read[x!!i]
n x|x<20=o!x|0<1="0066555766"!div x 10+o!mod x 10
f x=zipWith(\a b->a++" is "++b++".")l(tail l)where l=map show(takeWhile(/=4)$iterate n x)++["4","magic"]
main=readLn>>=mapM putStrLn.f

И немного читабельнее -

ones = [4,3,3,5,4,4,3,5,5,4,3,6,6,8,8,7,7,9,8,8]
tens = [0,0,6,6,5,5,5,7,6,6]

n x = if x < 20 then ones !! x else (tens !! div x 10) + (ones !! mod x 10)

f x = zipWith (\a b -> a ++ " is " ++ b ++ ".") l (tail l)
    where l = map show (takeWhile (/=4) (iterate n x)) ++ ["4", "magic"]
    
main = readLn >>= mapM putStrLn . f
Matajon
источник
4

Версия C ++ Stdio, уменьшенная: 196 символов

#include <cstdio>
#define P;printf(
char*o="43354435543668877988";main(int p){scanf("%d",&p)P"%d",p);while(p!=4){p=p<20?o[p]-48:"0366555966"[p/10]-96+o[p%10]P" is %d.\n%d",p,p);}P" is magic.\n");}

Версия C ++ Iostreams, уменьшенная: 195 символов

#include <iostream>
#define O;std::cout<<
char*o="43354435543668877988";main(int p){std::cin>>p;O p;while(p!=4){p=p<20?o[p]-48:"0366555966"[p/10]-96+o[p%10]O" is "<<p<<".\n"<<p;}O" is magic.\n";}

Исходный, без минификации: 344 символа

#include <cstdio>

int ones[] = { 4, 3, 3, 5, 4, 4, 3, 5, 5, 4, 3, 6, 6, 8, 8, 7, 7, 9, 8, 8 };
int tens[] = { 0, 3, 6, 6, 5, 5, 5, 9, 6, 6 };

int n(int n) {
    return n<20 ? ones[n] : tens[n/10] + ones[n%10];
}

int main(int p) {
    scanf("%d", &p);
    while(p!=4) {
        int q = n(p);
        printf("%i is %i\n", p, q);
        p = q;
    }
    printf("%i is magic\n", p);
}
Карл фон Моор
источник
Исправлена. Это также сделало его немного короче.
Mike DeSimone,
Отлично сделано. (Я много смеялся над стандартной головоломкой из 20 символов!)
Platinum Azure
Да, это был настоящий хедбангер, пока меня не осенило, что #defineон будет еще короче, так как может заменить несколько жетонов.
Mike DeSimone
printf("is magic".\n)=> puts. printf("%d",p)=> puts(atoi(p)). Не только короче, но и быстрее.
Ben Voigt
2
@Mike DeSimone: Думаю, while(p!=4)можно было бы сократить до while(p-4). Один цельный персонаж, я знаю, но все же. :-)
Platinum Azure
3

Delphi: 329 символов

Однострочная версия:

program P;{$APPTYPE CONSOLE}uses SysUtils;const S=65;A='EDDFEEDFFEDGGIIHHJII';B='DGGFFFJGG';function Z(X:Byte):Byte;begin if X<20 then Z:=Ord(A[X+1])-S else Z:=(Ord(B[X DIV 10])-S)+Z(X MOD 10)end;var X,Y:Byte;begin Write('> ');ReadLn(X);repeat Y:=Z(X);WriteLn(Format('%d is %d.',[X,Y]));X:=Y;until X=4;WriteLn('4 is magic.');end.

Отформатирован:

program P;

{$APPTYPE CONSOLE}

uses
  SysUtils;

const
  S = 65;
  A = 'EDDFEEDFFEDGGIIHHJII';
  B = 'DGGFFFJGG';

function Z(X:Byte):Byte;
begin
  if X<20
  then Z := Ord(A[X+1])-S
  else Z := (Ord(B[X DIV 10])-S) + Z(X MOD 10);
end;

var
  X,Y: Byte;

begin
  Write('> ');
  ReadLn(X);

  repeat
    Y:=Z(X);
    WriteLn(Format('%d is %d.' , [X,Y]));
    X:=Y;
  until X=4;

  WriteLn('4 is magic.');
end.

Наверное, хватит еще немного ... :-P

Йорн Э. Ангельтвейт
источник
3

C # 314 286 283 274 289 273 252 символа.

Squished:

252 

Обычный:

using C = System.Console;
class P
{
    static void Main()
    {
        var x = "4335443554366877798866555766";
        int m, o, v = int.Parse(C.ReadLine());
        do {
            C.Write("{0} is {1}.\n", o = v, v == 4 ? (object)"magic" : v = v < 20 ? x[v] - 48 : x[17 + v / 10] - 96 + ((m = v % 10) > 0 ? x[m] : 48));
        } while (o != 4);
        C.ReadLine();
    }
}

Edit Dykam: сделал довольно осторожные вставки и изменения:

  • Измененный l.ToString () в гипсе , чтобы 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, добавлена ​​правильная арифмика, чтобы исправить это.

mdm20
источник
Ага, получилось короче Java версии.
Dykam
3

Lua, 176 символов

o={[0]=4,3,3,5,4,4,3,5,5,4,3,6,6,8,8,7,7,9,8,8}t={3,6,6,5,5,5,7,6,6}n=0+io.read()while n~=4 do a=o[n]or o[n%10]+t[(n-n%10)/10]print(n.." is "..a..".")n=a end print"4 is magic."

или

  o={[0]=4,3,3,5,4,4
  ,3,5,5,4,3,6,6,8,8
  ,7,7,9,8,8}t={3,6,
   6,5,5,5,7,6,6}n=
   0+io.read()while
   n ~= 4 do a= o[n
   ]or o[n%10]+t[(n
   -n%10)/10]print(
n.." is "..a.."." )n=a
end print"4 is magic."
гвелл
источник
3

C - без числовых слов

180 175 * 172 167 символов

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

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 вместо аргументов командной строки сэкономило еще больше, что привело к чистой экономии.

P Daddy
источник
2

perl, 123122 символа

Просто понял, что нет необходимости выводить в STDOUT, поэтому вместо этого выведите в STDERR и отбросьте другой символ.

@u='0335443554366887798866555766'=~/./g;$_+=<>;warn"$_ is ",$_=$_-4?$_<20?$u[$_]||4:$u[chop]+$u[$_+18]:magic,".\n"until/g/

И версия, которая возвращает прописанные числа:

279 278 276 280 знаков

@p=(Thir,Four,Fif,Six,Seven,Eigh,Nine);@n=("",One,Two,Three,Four,Five,@p[3..6],Ten,Eleven,Twelve,map$_.teen,@p);s/u//for@m=map$_.ty,Twen,@p;$n[8].=t;sub n{$n=shift;$n?$n<20?$n[$n]:"$m[$n/10-2] $n[$n%10]":Zero}$p+=<>;warnt$m=n($p)," is ",$_=$p-4?n$p=()=$m=~/\w/g:magic,".\n"until/c/

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

«Меня не волнует, как вы разделяете токены слов, хотя их следует разделять»

Хотя это вроде как ласково. Более правильная версия на

282 281 279 283 знаков

@p=(Thir,Four,Fif,Six,Seven,Eigh,Nine);@n=("\x8",One,Two,Three,Four,Five,@p[3..6],Ten,Eleven,Twelve,map$_.teen,@p);s/u//for@m=map$_.ty,Twen,@p;$n[8].=t;sub n{$n=shift;$n?$n<20?$n[$n]:"$m[$n/10-2]-$n[$n%10]":Zero}$p+=<>;warn$m=n($p)," is ",$_=$p-4?n$p=()=$m=~/\w/g:magic,".\n"until/c/
пользователь397369
источник
1

Python:

#!/usr/bin/env python

# Number of letters in each part, we don't count spaces
Decades = ( 0, 3, 6, 6, 6, 5, 5, 7, 6, 6, 0 )
Smalls  = ( 0, 3, 3, 5, 4, 4, 3, 5, 5, 4 )
Teens  =  ( 6, 6, 8, 8, 7, 7, 9, 8, 8 )

def Count(n):
    if n > 10 and n < 20: return Teens[n-11]
    return   Smalls[n % 10 ] + Decades [ n / 10 ]

N = input()

while N-4:
    Cnt = Count(N)
    print "%d is %d" % ( N, Cnt)
    N = Cnt

print "4 is magic"
Влад
источник
4
Мне это нравится. Хотя, возможно, вы могли бы немного его подтянуть.
Josh K
@Vlad: ввод следует читать из stdin, а не из аргументов. Это означает, что вы можете просто использовать N = input()(или raw_input()) и удалить sysматериал.
kennytm
Также вы можете включить в smalls подростков, тогда оператор if будет только «if n <20: return Smalls [n]». Смоллс по-прежнему будет работать для случая> = 20 из-за модуля на 10.
Джон Смок
5
Должно быть, это первый раз, когда я вижу (полностью необязательно) she-bangв ответе на код-гольф ;-)
ChristopheD,
Похоже, хорошее начало ... Определенно затяните, даже Python не нуждается в ВСЕХ этих пробелах. :-) Кроме того, как указывает Ферруччо, 0 не работает, в частности, кажется, что он заходит в бесконечный цикл.
Platinum Azure
1

C ++, 171 символ (#include опущено)

void main(){char x,y,*a="03354435543668877988";scanf("%d",&x);for(;x-4;x=y)y=x?x<19?a[x]-48:"_466555766"[x/10]+a[x%10]-96:4,printf("%d is %d.\n",x,y);puts("4 is magic.");}
Том Сиргедас
источник
Я думаю, что если вы считаете, что это C, вы можете избежать необходимости, #includeпотому что функции будут просто принимать intпараметры. Вы даже можете сохранить удар, сделав mainвозврат int.
Гейб
1

Рубин, 164 символа

n=gets.to_i;s="03354435543668877987";if n==0;puts"0 is 4.";else;puts"#{n} is #{n=(n<20)?s[n]-48:"0066555766"[n/10]-48+s[n%10]-48}." until n==4;end;puts"4 is magic."

расшифровано:

n = gets.to_i
s = "03354435543668877987"
if n == 0
  puts "0 is 4."
else
  puts "#{n} is #{n = (n < 20) ? s[n] - 48 : "0066555766"[n / 10] - 48 + s[n % 10] - 48}." until n == 4
end

puts "4 is magic."
Джон Смок
источник
Хорошее решение Ruby, сохраняя его простоту. :-) (+1)
Platinum Azure
Однако простота - не оправдание для того, чтобы держать его слишком долго ;-)
Joey
Я думаю, вы можете заменить if n == 0 на if! N
Винсент
2
В Руби? Я всегда думал, что все значения, кроме false и nil, оцениваются как true :-(
Platinum Azure
1

Lua 185 190 199

добавлены точки, добавлены io.read, удалены () при последней печати

 n=io.read();while(n~=4)do m=('43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:'):sub(n+1):byte()-48;print(n,' is ',m,'.')n=m;end print'4 is magic.'

с переносом строки

 n=io.read()
 while (n~=4) do
    m=('43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:'):sub(n+1):byte()-48;
    print(n,' is ',m,'.')
    n=m;
 end 
 print'4 is magic.'
Ник
источник
Требуется n=io.read()(+11 символов) для соответствия правилу чтения числа со стандартного ввода. Изменение print('4 is magic.')на print'4 is magic.'сэкономит 2 символа. Удаление ;после )сохранит 1 символ. В printиспользовании запятых , кажется , как обман, но спекуляция неясно. Можно также изменить его на, print(n,'is',m,'.')чтобы сохранить 2 символа.
gwell
Отображаются ли запятые как новые строки в Lua отдельно? Я давно не пользовался им.
Ник Ван Брант,
Запятые отображаются в виде вкладок.
gwell
0

Код PhP

function get_num_name($num){  
    switch($num){  
        case 1:return 'one';  
    case 2:return 'two';  
    case 3:return 'three';  
    case 4:return 'four';  
    case 5:return 'five';  
    case 6:return 'six';  
    case 7:return 'seven';  
    case 8:return 'eight';  
    case 9:return 'nine';  
    }  
}  

function num_to_words($number, $real_name, $decimal_digit, $decimal_name){  
    $res = '';  
    $real = 0;  
    $decimal = 0;  

    if($number == 0)  
        return 'Zero'.(($real_name == '')?'':' '.$real_name);  
    if($number >= 0){  
        $real = floor($number);  
        $decimal = number_format($number - $real, $decimal_digit, '.', ',');  
    }else{  
        $real = ceil($number) * (-1);  
        $number = abs($number);  
        $decimal = number_format($number - $real, $decimal_digit, '.', ',');  
    }  
    $decimal = substr($decimal, strpos($decimal, '.') +1);  

    $unit_name[1] = 'thousand';  
    $unit_name[2] = 'million';  
    $unit_name[3] = 'billion';  
    $unit_name[4] = 'trillion';  

    $packet = array();    

    $number = strrev($real);  
    $packet = str_split($number,3);  

    for($i=0;$i<count($packet);$i++){  
        $tmp = strrev($packet[$i]);  
        $unit = $unit_name[$i];  
        if((int)$tmp == 0)  
            continue;  
        $tmp_res = '';  
        if(strlen($tmp) >= 2){  
            $tmp_proc = substr($tmp,-2);  
            switch($tmp_proc){  
                case '10':  
                    $tmp_res = 'ten';  
                    break;  
                case '11':  
                    $tmp_res = 'eleven';  
                    break;  
                case '12':  
                    $tmp_res = 'twelve';  
                    break;  
                case '13':  
                    $tmp_res = 'thirteen';  
                    break;  
                case '15':  
                    $tmp_res = 'fifteen';  
                    break;  
                case '20':  
                    $tmp_res = 'twenty';  
                    break;  
                case '30':  
                    $tmp_res = 'thirty';  
                    break;  
                case '40':  
                    $tmp_res = 'forty';  
                    break;  
                case '50':  
                    $tmp_res = 'fifty';  
                    break;  
                case '70':  
                    $tmp_res = 'seventy';  
                    break;  
                case '80':  
                    $tmp_res = 'eighty';  
                    break;  
                default:  
                    $tmp_begin = substr($tmp_proc,0,1);  
                    $tmp_end = substr($tmp_proc,1,1);  

                    if($tmp_begin == '1')  
                        $tmp_res = get_num_name($tmp_end).'teen';  
                    elseif($tmp_begin == '0')  
                        $tmp_res = get_num_name($tmp_end);  
                    elseif($tmp_end == '0')  
                        $tmp_res = get_num_name($tmp_begin).'ty';  
                    else{  
                        if($tmp_begin == '2')  
                            $tmp_res = 'twenty';  
                        elseif($tmp_begin == '3')  
                            $tmp_res = 'thirty';  
                        elseif($tmp_begin == '4')  
                            $tmp_res = 'forty';  
                        elseif($tmp_begin == '5')  
                            $tmp_res = 'fifty';  
                        elseif($tmp_begin == '6')  
                            $tmp_res = 'sixty';  
                        elseif($tmp_begin == '7')  
                            $tmp_res = 'seventy';  
                        elseif($tmp_begin == '8')  
                            $tmp_res = 'eighty';  
                        elseif($tmp_begin == '9')  
                            $tmp_res = 'ninety';  

                        $tmp_res = $tmp_res.' '.get_num_name($tmp_end);  
                    }  
                    break;  
            }  

            if(strlen($tmp) == 3){  
                $tmp_begin = substr($tmp,0,1);  

                $space = '';  
                if(substr($tmp_res,0,1) != ' ' && $tmp_res != '')  
                    $space = ' ';  

                if($tmp_begin != 0){  
                    if($tmp_begin != '0'){  
                        if($tmp_res != '')  
                            $tmp_res = 'and'.$space.$tmp_res;  
                    }  
                    $tmp_res = get_num_name($tmp_begin).' hundred'.$space.$tmp_res;  
                }  
            }  
        }else  
            $tmp_res = get_num_name($tmp);  
        $space = '';  
        if(substr($res,0,1) != ' ' && $res != '')  
            $space = ' ';  
        $res = $tmp_res.' '.$unit.$space.$res;  
    }  

    $space = '';  
    if(substr($res,-1) != ' ' && $res != '')  
        $space = ' ';  

    if($res)  
        $res .= $space.$real_name.(($real > 1 && $real_name != '')?'s':'');  

    if($decimal > 0)  
        $res .= ' '.num_to_words($decimal, '', 0, '').' '.$decimal_name.(($decimal > 1 && $decimal_name != '')?'s':'');  
    return ucfirst($res);  
}  

//////////// тестирование ////////////////

 $str2num = 12;
    while($str2num!=4){
        $str = num_to_words($str2num, '', 0, '');  
        $str2num = strlen($str)-1;
        echo $str . '=' . $str2num .'<br/>';
        if ($str2num == 4)
            echo 'four is magic';
    }

////// Полученные результаты /////////

Twelve =6
Six =3
Three =5
Five =4
four is magic
Разработчик
источник
4
@wallacoloo: Плохое решение для грязного языка: D
Томас Эдинг,
5
Или намного короче 178 символов:$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";
gnarf
Хорошая шутка. :-D Так хорошо запрограммирован.
Tom Pažourek
0

Perl - 130 символов


5.12.1 (130 символов) 121 123 132 136 140

#        1         2         3         4         5         6         7         8         9        100        11        12        13       14    
#23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123

@u='4335443554366887798866555766'=~/./g;$_=pop;say"$_ is ",$_=$_-4?$_<20?$u[$_]:$u[$_/10+18]+(($_%=10)&&$u[$_]):magic,"."until/\D/


5.10.1 (134 символа) 125 127 136 140 144

#        1         2         3         4         5         6         7         8         9        100        11        12        13       14    
#23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 1234

@u='4335443554366887798866555766'=~/./g;$_=pop;print"$_ is ",$_=$_-4?$_<20?$u[$_]:$u[$_/10+18]+(($_%=10)&&$u[$_]):magic,".\n"until/\D/


История изменений:

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 и Платиновая лазурь .

vol7ron
источник
Когда вы избавились от $_%10&&...конструкции, вы нарушили спецификацию для входов 20,30,40, ...
моб
+1 Отлично сделано. Однако вы перешли из стандартного ввода в аргументы :-(
Platinum Azure
Правильно, заменено на ARGV , которое заполняется STDIN:) или .. echo bar | xargs perl foo.pl, технически передано из echo в аргументы для perl :)
vol7ron
0

Shameless Perl с числовыми словами (329 символов)

Адаптировано непосредственно из кода P Daddy на C, с некоторыми настройками, чтобы p()заставить его делать то же самое, используя примитивы Perl вместо примитивов C, и в основном переписанный основной цикл. См. Его для объяснения. Новые строки необязательны.

@t=(qw(zero 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 4SmagicT)," is ",".\n");
sub p{local$_=$t[pop];1while s/[0-Z]/$t[-48+ord$&]/e;
print;length}$_=<>;chop;while($_-4){
$_=($_>19?(p($_/10+18),$_&&print("-"),$_%=10)[0]:0)+p$_;
p 35;p$_;p 36}p 34

Боковое примечание: очень плохо, что perl printпросто возвращает true / false; если бы он вернул счет, это спасло бы меня 7 ударов.

хоббс
источник
0

Рубин, 141 символ:

n=gets.to_i;m="4335443554366887798866555766";loop{s=n;n=n>20?m[18+n/10]+m[n%10]-96: m[n]-48;puts"#{s} is #{n==s ? 'magic': n}.";n==s &&break}
Кшиштоф
источник
-7
while(true)
{
    string a;
    ReadLine(a)
    WriteLine(4);

}
user368038
источник