Гольф кода: Четыре является волшебным

88
задан 7 revs, 3 users 98% 23 May 2017 в 12:02
поделиться

29 ответов

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."
57
ответ дан 24 November 2019 в 07:23
поделиться

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"
1
ответ дан 24 November 2019 в 07:23
поделиться

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);
}
4
ответ дан 24 November 2019 в 07:23
поделиться

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$_

Трюки:

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

6
ответ дан 24 November 2019 в 07:23
поделиться

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.'
9
ответ дан 24 November 2019 в 07:23
поделиться

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)))

Giving

>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.
30
ответ дан 24 November 2019 в 07:23
поделиться

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. 
10
ответ дан 24 November 2019 в 07:23
поделиться

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.
10
ответ дан 24 November 2019 в 07:23
поделиться

Python, 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
ответ дан 24 November 2019 в 07:23
поделиться

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
4
ответ дан 24 November 2019 в 07:23
поделиться

Ruby, 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."
1
ответ дан 24 November 2019 в 07:23
поделиться

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
85
ответ дан 24 November 2019 в 07:23
поделиться

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

Squished:

252 

Normal:

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 () на приведение к объекту из строка «магия» .
  • Создана временная переменная o , поэтому я мог переместить разрыв за пределы цикла for , то есть, в результате получился do-while .
  • Встраивает присвоение o , а также назначение v , продолжая вставку вычисления l в аргументы функции в целом, устраняя необходимость в ] l . Также встроено присвоение м .
  • Удален пробел в int [] x , int [] x тоже допустим.
  • Пытался преобразовать массив в строковое преобразование, но с использованием System.Linq было слишком много, чтобы сделать это улучшением.

Редактировать 2 Дикам Изменил массив int на массив / строку char, добавил правильную арифмику, чтобы исправить это.

3
ответ дан 24 November 2019 в 07:23
поделиться

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
ответ дан 24 November 2019 в 07:23
поделиться

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.");}
1
ответ дан 24 November 2019 в 07:23
поделиться

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

3
ответ дан 24 November 2019 в 07:23
поделиться

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
ответ дан 24 November 2019 в 07:23
поделиться

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.')

Вывод:

ninety nine is ten.
ten is three.
three is five.
five is four.
four is magic.
5
ответ дан 24 November 2019 в 07:23
поделиться

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

Expanded:

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

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

  • Создайте таблицу поиска для длин имени номера на основе цифр, которые появляются в номере.
  • Использовать поиск по массиву символов в строке и арифметические операции с символами вместо числового массива.
  • Используйте псевдоним имени класса для сокращения консоли . - С.
  • Используйте условный (тернарный) оператор (?: ) вместо if / else .
  • Используйте \ n с Запишите escape-код вместо WriteLine
  • Используйте тот факт, что C # имеет определенный порядок оценки, чтобы разрешить назначения внутри ] Запись вызов функции
  • Используйте выражения присваивания, чтобы исключить лишние операторы и, таким образом, лишние фигурные скобки
6
ответ дан 24 November 2019 в 07:23
поделиться

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.");
}
8
ответ дан 24 November 2019 в 07:23
поделиться

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

Edit: No longer use hex, this is less keystrokes

9
ответ дан 24 November 2019 в 07:23
поделиться

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

Это число разделяет на десятки и единицы и суммирует их вверх. Здесь злоупотребляют нежелательным свойством псевдотроичного оператора a и b или 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."
21
ответ дан 24 November 2019 в 07:23
поделиться

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 'M' - ASCII '0') в поисковой таблице. Это строка evL , поэтому она выводит e и v , а затем вызывает себя снова с индексом 28-й записи в таблице поиска, который равен en , и выводится дословно.Это полезно, потому что en также используется в eL для een (используется после восемь в восемнадцать ), который используется в to для teen (используется для всех остальных -teen имени).

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

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

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

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

По поводу отсутствия #include

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

Выходные данные

Выходные данные такие, как ожидалось:

0
zero is four.
four is magic.
1
one is three.
three is five.
five is four.
four is magic.
4
four is magic.
20
twenty is six.
six is three.
three is five.
five is four.
four is magic.
21
twenty-one is nine.
nine is four.
four is magic.

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

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

20
ответ дан 24 November 2019 в 07:23
поделиться

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/
2
ответ дан 24 November 2019 в 07:23
поделиться

Lua 185 190 199

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

 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.'
1
ответ дан 24 November 2019 в 07:23
поделиться

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

Достаточно адаптирован непосредственно из кода C P Daddy, с некоторыми изменениями в 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
ответ дан 24 November 2019 в 07:23
поделиться

Код 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
0
ответ дан 24 November 2019 в 07:23
поделиться
while(true)
{
    string a;
    ReadLine(a)
    WriteLine(4);

}
-7
ответ дан 24 November 2019 в 07:23
поделиться

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
2010714:0025 - ($_%10&&$u[$_%10])$u[$_%10]
2010713:2340 - while$_until/\D/ + удалены лишние скобки
2010713: xxxx - $=<>;chop;$_=pop; - любезность к mobrule


Примечание: Я устал улучшать чужие ответы в комментариях, так что теперь я жадный и могу просто добавить свои изменения сюда :) Это ответ от Platinum Azure - частично заслуга Hobbs, mobrule и Platinum Azure.

0
ответ дан 24 November 2019 в 07:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: