Код гольфу: Чотири - це магія


88

Головоломка

Маленька загадка, яку я почув, коли навчався в середній школі, виглядала приблизно так ...

  • Той, хто питає, попросить мене дати йому номер;
  • Почувши число, допитувач повторював би його якусь трансформацію неодноразово (наприклад, він міг би сказати, що десять - це три ), поки врешті не дійшов до цифри 4 (в цей момент він закінчив би з чотирма - це магія ).
  • Здається, будь-яке число зрештою перетворюється на чотири, незважаючи ні на що.

Метою було спробувати з’ясувати функцію перетворення, а потім мати можливість надійно спроектувати цю головоломку самостійно.

Рішення

Функція перетворення на будь-якому кроці повинна була

  • Візьміть номер, про який йде мова,
  • Підрахуйте кількість букв у поданні англійського слова, ігноруючи дефіс або пробіли або "і" (наприклад, "десять" містить 3 літери, "тридцять чотири" має 10 букв, "сто сорок три") містить 20 букв).
  • Поверніть цю кількість літер.

Для всіх чисел, які я коли-небудь піклувався про тестування, це сходиться до 4. Оскільки в "чотири" також є чотири літери, тут буде нескінченний цикл; натомість це просто згадується як магія за домовленістю для завершення послідовності.

Змагання

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

Зокрема:

  1. Рішення повинні бути повноцінними програмами самі по собі. Вони не можуть бути просто функціями, які приймають число - коефіцієнт на вході.
  2. Введення потрібно зчитувати зі стандартного вводу. (Конвеєр з "ехо" або використання перенаправлення вводу - це добре, оскільки це також йде від stdin)
  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.

Переможцем є найкоротша подача за кількістю символів вихідного коду, що також є правильним .

БОНУС

Ви також можете спробувати написати версію коду, яка друкує АНГЛІЙСЬКІ НАЗВИ для чисел з кожним додатком функції перетворення. Початкове введення все ще є числовим, але рядки виводу повинні мати слово у вигляді числа.

(Подвійний бонус за малювання фігур за допомогою коду)

(EDIT) Деякі роз’яснення:

  1. Я дійсно хочу, щоб слово відображалося з обох сторін у всіх відповідних випадках, наприклад Nine is four. Four is magic.
  2. Однак я не дбаю про капіталізацію. І мені байдуже, як ви розділяєте лексеми слів, хоча їх слід розділяти: ninety-nineце добре, ninety nineце добре, ninetynineце не добре.

Я розглядаю їх як окрему категорію для бонусного змагання щодо виклику, тому, якщо ви вирішите це зробити, не хвилюйтеся, що ваш код довший за числову версію.

Не соромтеся подавати одне рішення для кожної версії.


1
Наскільки високе число нам слід обробити? <100? <1000? <1000000? <2 ** 31?
P Daddy

1
Оскільки для цього потрібно лише перейти від 0 до 99, я підозрюю, що швидким, коротким рішенням буде жорстке кодування значень, до яких відображається 0-99, а потім цикл, поки ви не досягнете 4. Після цього починається мікрозмінювання.
Беска

@P Daddy ... частина 6 говорить лише 0-99.
Беска


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."

чому це так далеко? він коротший за шепелявий і не використовує вбудовану функцію форматування
Клаудіу

36
Мені подобається, як закінчується код "magic.", він майже підсумовує це.
Aistina

@Aistina: Думаю, це легко зробити у цьому виклику. :-)
Платиновий блакитний

9
@Aistina: ха-ха, це якось смішно. "mumbo jumbo yada yada..magic"
vol7ron

1
@P Daddy The dвитягується за допомогою )as 100і використовується як радіус для базового перетворення.
Набб

85

Перл, приблизно 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, якщо ви підраховуєте пробіли в '. '(пробіл є
літералом

Трохи довше, але творчість у моїй книзі робить довгий шлях.
Беска

@Platinum Azure та інші: Він отримує свої вказівки від stdin. Це спосіб зробити це в Perl. (Можливо, він змінив це після вашого коментаря?)
Френк

@P Daddy: стогне, але все одно +1 до вашого коментаря
Platinum Azure

30

Common Lisp 157 Chars

Нова більш відповідна версія, яка тепер читає форму стандартного введення та ігнорує пробіли та дефіси:

(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.

5
Я думав, що "двадцять чотири" має лише 10 букв?
kennytm

1
Цифри після "є" теж повинні бути текстовими.
Mike DeSimone

5
чому це так високо? інші не використовують вбудовану функцію форматування і вони мають менше символів
Клавдіу

3
@Claudiu, тому що Common Lisp надзвичайний.
Mornedhel

3
Не має значення, скільки ударів ви зробите, якщо ви не потрапите м’яч у лунку. Люди, здається, забувають, що коли вони висловлюються за неправильні рішення.
Mark Peters

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."

Вибачте, я спеціально хотів зупинитись саме через такі речі. :-) Хороший запис, хоча! (EDIT: Я не знаю Python, але чи могли б ви n,"is",p,"."? Я думаю, ви все одно збережете деякі символи, якщо я правильно рахую)
Platinum Azure

2
@Plat: Це призведе до додаткового простору перед ..
kennytm

@KennyTM: О, ну, я мав би це помітити навіть із фрагмента. Ой! Ну, в будь-якому випадку, як я вже сказав, деякі технічні характеристики були спеціально розроблені, щоб трохи ускладнити ситуацію. :-)
Platinum Azure

Чи можемо ми це скоротити, використовуючи вищу базу, ніж 36?
MikeD

@MikeD: Ні. З документів Python: " Базовий параметр дає основу для перетворення (яка за замовчуванням дорівнює 10) і може бути будь-яким цілим числом у діапазоні [2, 36] або нулем." Тепер ви могли б бути в змозі використати іншу функцію , ніж int(), скажімо , що - то з structабо base64модулів ...
Майк DeSimone

20

С - з числовими словами

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. Обробка нулів доданих символів, але використання stdin замість аргументів командного рядка, а також пара інших оптимізацій зберегли однакову кількість символів, що призвело до змивання.

Вимоги були змінені, щоб чітко пояснити, що числове слово слід друкувати з обох боків від "є". Ця нова версія відповідає цій вимозі та реалізує ще пару оптимізацій, щоб (зважаючи на) врахувати необхідний додатковий розмір.


Це легко мій улюблений варіант відповідей ... Браво, молодець. +1 для вас, і якби я міг поставити дві галочки, я б.
Platinum Azure

5
Це цікаво читати, я думаю, я буду використовувати ці цифри відтепер у повсякденному житті. Шість, сім, вісім, дев'ять, тел, елем, дванадцять, енпі, четвірка, п'ятдесят, шість бай, сім, монета, вісім, дев'ять, дванадцять ... =)
обдурити

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

(Не те, що я серйозно пропоную вам це зробити ... справді я просто хотів написати КТЕ)

Використовувати:

M 95

Повернення

p                n
----------- ---- -----------
95          is   10.
10          is   3.
3           is   5.
5           is   4.
4 is magic.

Ви не можете просто надрукувати окремі результати, замість того щоб повернути таблицю? Це зробило б результат вигляду приємнішим.
Джої

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 без імпорту, клас def або основний def.
Mark Peters

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 Влада, запозичив фокус у рішенні С ++ Тома Сіргедаса, щоб вичавити ще кілька символів)

розширена версія:

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 - -27. Помилка сегментації
Кейсі

@Casey - виклик scanf () був трохи схематичним. Це було читання тексту на знак. Я виходив з цим на OSX, і в Windows це працювало, але при виході з ладу. Отже, я знову зробив ін-та. Я зрозумів, що можу скинути ключове слово int, зробивши для них параметри, використовуючи позначення K&R. Результат безпечніший і на один символ коротший.
Ферруччо

Ви можете зберегти 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 символів.

Сквоя:

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.
  • Використовуйте \nз Writeтікання кодом замістьWriteLine
  • Використовуйте той факт, що C # має визначений порядок оцінки, щоб дозволити призначення всередині Write виклику функції
  • Використовуйте вирази присвоєння, щоб усунути зайві твердження, а отже, і додаткові дужки

int[] zбуде коротшим, оскільки йому це не потрібноnew[]
Джої

Переглянуто для використання арифметики символів замість пошуку масиву.
Л.Бушкін

@ mdm20: Ти маєш рацію. У мене була помилка в таблиці пошуку. Виправлено зараз.
Л.Бушкін

Ну, дванадцятий раз - це принада: * 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 зараз.
  • Перероблено якийсь надлишковий код.
  • Ключове слово з останнім поверненням у r непотрібне, ще поголено.
  • Масовий рефакторинг за коментарями; на жаль, я міг отримати його лише до 149, тому що мені довелося виправити помилку, яка була присутня як у моєму попередньому коді, так і у версіях коментаторів.
  • Спроба простого слова "магія".

Давайте запустимо цю кульку скромною спробою в Perl.

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

Фокуси:

Забагато!


ЗМІНИ! Як я ніколи не тестував, що ніколи не дізнаюся.
Platinum Azure

У вас там мертвий код? Я не бачу, як необхідний особливий випадок нуля, коли $ u [0] дорівнює 4. У мене є, здавалося б, робоча версія вашого коду @ 166 символів, і я думаю, що в ньому є місце, щоб стати трохи коротшим за це.
hobbs

@hobbs: Хороший момент, я ще раз подивлюсь. Історія полягає в тому, що я пройшов півдороги через кілька переглядів і раптом все зламалося (приблизно в той момент, коли я вибрав мати 4 -> 0). Я думаю, що ви зараз маєте рацію :-)
Platinum Azure

Я не вважаю себе чудовим програмістом Perl, але ви можете зменшити деякі символи: @u=split$x,'43350435543668877988';ваші коми використовують непотрібні 19 символів, розділяючи на undefподіли на кожному символі, я використовую $xяк невизначену змінну, щоб замінити `undef` - всього економія: 11 символів. Крім того, видаліть min, 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.')

Вихід:

дев'яносто дев'ять - це десять.
десять - це три.
три - це п’ять.
п’ять - це чотири.
чотири - це магія.

4

Хаскелл, 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

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

Дельфи: 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 символів.

Сквоя:

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();
    }
}

Редагувати Dykam: Зробив досить обережні вставки та зміни:

  • Змінений l.ToString () в гіпсі , щоб objectз string "magic".
  • Створив тимчасову змінну o, щоб я міг перемістити breakзовнішню частину forциклу, тобто привести до do-while.
  • Вказав oприсвоєння, як і vприсвоєння, продовжуючи вставляти обчислення lв аргументи функції взагалі, усуваючи потребу в l. Також вказано призначення m.
  • Видалено пробіл у int[] x, також int[]xє законним.
  • Спробував перетворити масив на рядкове перетворення, але цього using System.Linqбуло занадто багато, щоб зробити це покращенням.

Редагувати 2 Dykam Змінив масив int на масив / рядок char, додав належну арифметику, щоб це виправити.


Так, отримав це коротше, ніж версія Java.
Дикам

3

Луа, 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

З - без числових слів

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. Обробка нуля доданих символів, але використання stdin замість аргументів командного рядка заощадило ще більше, що призвело до чистої економії.


2

perl, 123 122 символи

Щойно зрозумів, що немає вимоги виводити на 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/

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
Мені це подобається. Напевно, ви могли б трохи його підтягнути.
Джош К

@Vlad: Введення слід читати з stdin, а не з аргументів. Це означає, що ви можете просто використовувати N = input()(або raw_input()) і усунути sysречі.
kennytm

Крім того, ви можете зробити так, щоб маленькі особи включали підлітків, тоді оператор if буде лише "if n <20: return Smalls [n]". Смоллс все одно працював би у випадку> = 20 через модуль на 10.
Джон Смок,

5
Це, мабуть, перший раз, коли я бачу (повністю необов’язково) she-bangу відповіді на код-гольф ;-)
ChristopheD

Схоже на хороший початок ... Безумовно, посиліть його, навіть Python не потребує ВСІХ цих пробілів. :-) Крім того, як зазначає Ферруччо, 0 не працює, зокрема, здається, він потрапляє в нескінченний цикл.
Platinum Azure

1

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

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

Спрощення не є виправданням для того, щоб тримати його занадто довго,
Джої,

Я думаю, ви можете замінити 'if n == 0' на 'if! N'
Вінсент,

2
У Рубі? Я завжди думав, що всі значення, крім false і nil, оцінюються як істинні :-(
Platinum Azure

1

Луа 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, окремо? Минув деякий час, як Ive використовував його.
Нік Ван Брант,

Коми відображаються як вкладки.
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
Thomas Eding

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 Так добре запрограмований.
Том Пажурек,

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- повернув зміни під увагу mobrule , але ($_%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, ...
моб

+1 Чудово зроблено. Ти все ж вийшов зі stdin в аргументах :-(
Platinum Azure

Праворуч, замінено на ARGV, який заповнюється STDIN:) або .. echo bar | xargs perl foo.pl, технічно переведений з відлуння в аргументи для perl :)
vol7ron

0

Безсоромна Perl з числовими словами (329 символів)

Адаптований досить безпосередньо з коду P Daddy's C, з деякими налаштуваннями, щоб p()змусити його робити те саме, використовуючи примітиви Perl замість C, і переважно переписаний mainloop. Подивіться на його пояснення. Нові рядки необов’язкові.

@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}

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.