Code Golf: Four to magia

88

Zagadka

Mała zagadka, którą usłyszałem, gdy byłem w liceum, poszła mniej więcej tak ...

  • Pytający prosi mnie o podanie numeru;
  • Po usłyszeniu liczby pytający dokonywałby na niej jakiejś transformacji wielokrotnie (na przykład, mógłby powiedzieć, że dziesięć to trzy ), aż w końcu dotarłby do liczby 4 (w którym to momencie zakończyłby z czterema to magia ).
  • Każda liczba wydaje się ostatecznie przekształcać w cztery, bez względu na wszystko.

Celem była próba zrozumienia funkcji transformacji, a następnie umiejętność samodzielnego wykonania tej zagadki.

Rozwiązanie

Funkcją transformacji na każdym kroku było

  • Weź podany numer,
  • Policz liczbę liter w angielskiej reprezentacji słów, ignorując łącznik lub spacje lub „i” (np. „Dziesięć” ma 3 litery, „trzydzieści cztery” ma 10 liter, „sto czterdzieści trzy” zawiera 20 liter).
  • Zwróć tę liczbę liter.

Dla wszystkich liczb, które kiedykolwiek chciałem przetestować, zbiega się to do 4. Ponieważ „cztery” również mają cztery litery, powstałaby tutaj nieskończona pętla; zamiast tego jest zwyczajowo określany jako magia w celu zakończenia sekwencji.

Wyzwanie

Twoim wyzwaniem jest stworzenie fragmentu kodu, który odczyta liczbę od użytkownika, a następnie wydrukuje wiersze pokazujące, że funkcja transformacji jest wielokrotnie stosowana, aż do osiągnięcia „cztery jest magiczne”.

Konkretnie:

  1. Rozwiązania muszą być kompletnymi programami same w sobie. Nie mogą być po prostu funkcjami, które przyjmują liczbę - czynnik w danych wejściowych.
  2. Wejście należy czytać ze standardowego wejścia. (Piping z „echo” lub użycie przekierowania danych wejściowych jest w porządku, ponieważ działa to również ze standardowego wejścia)
  3. Dane wejściowe powinny mieć postać liczbową.
  4. Dla każdego zastosowania funkcji transformacji należy wydrukować wiersz:, a is b.gdzie a i b są liczbowymi postaciami liczb w transformacji.
  5. Wymagane są kropki (okresy)!
  6. Ostatnia linia powinna naturalnie powiedzieć 4 is magic..
  7. Kod powinien dawać poprawne dane wyjściowe dla wszystkich liczb od 0 do 99 .

Przykłady:

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

Zwycięzcą jest najkrótsze zgłoszenie według liczby znaków kodu źródłowego, co również jest poprawne .

PREMIA

Możesz także spróbować napisać wersję kodu, która wypisuje ANGIELSKIE NAZWY dla liczb przy każdym zastosowaniu funkcji transformacji. Oryginalne dane wejściowe są nadal numeryczne, ale wiersze wyjściowe powinny mieć postać słowa liczby.

(Podwójny bonus za rysowanie kształtów za pomocą kodu)

(EDYCJA) Kilka wyjaśnień:

  1. Chcę, aby słowo pojawiało się po obu stronach we wszystkich odpowiednich przypadkach, np Nine is four. Four is magic.
  2. Nie obchodzi mnie jednak kapitalizacja. I nie obchodzi mnie, jak rozdzielasz tokeny słów, chociaż powinny być oddzielone: ninety-ninejest w porządku, ninety ninejest w porządku, ninetyninenie jest w porządku.

Uważam, że jest to osobna kategoria dla konkurencji bonusowej w odniesieniu do wyzwania, więc jeśli zdecydujesz się na to, nie martw się, że twój kod będzie dłuższy niż wersja numeryczna.

Zapraszam do przesłania jednego rozwiązania dla każdej wersji.

Platinum Azure
źródło
1
Jak dużą liczbę powinniśmy obsłużyć? <100? <1000? <1000000? <2 ** 31?
P Daddy,
1
Ponieważ wystarczy tylko od 0 do 99, podejrzewam, że szybkim, krótkim rozwiązaniem byłoby zakodowanie na stałe wartości, na które mapowane są 0-99, a następnie zapętlenie, aż osiągniesz 4. Następnie rozpocznie się mikrouszkodzenie.
Beska
@P Tatusiu ... część 6 mówi tylko 0-99.
Beska
14
4 to magia tylko dlatego, że została wybrana przez uczciwy rzut kostką.
VirtuosiMedia

Odpowiedzi:

57

GolfScript - 101 96 93 92 91 90 94 86 bajtów

90 → 94: Naprawiono wynik dla wielokrotności 10
94 → 86.: Zrestrukturyzowany kod. Używanie podstawy 100 do usuwania znaków niedrukowalnych.
86 → 85: Krótszy rzut na strunę.

{n+~."+#,#6$DWOXB79Bd")base`1/10/~{~2${~1$+}%(;+~}%++=" is "\".
"1$4$4-}do;;;"magic."
Nabb
źródło
dlaczego to jest tak nisko? jest krótszy niż lisp i nie korzysta z wbudowanej funkcji formatowania
Claudiu
36
Podoba mi się, jak kończy się kod "magic.", to właściwie podsumowuje.
Aistina
@Aistina: Myślę, że to łatwe w tym wyzwaniu. :-)
Platinum Azure
9
@Aistina: haha, to trochę zabawne. „mumbo jumbo yada yada..magic”
vol7ron
1
@P Daddy The djest wyodrębniany przez )as 100i używany jako podstawa konwersji podstawowej.
Nabb
85

Perl, około 147 znaków

Luźno oparty na rozwiązaniu 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
mob
źródło
1
@Platinum Azure sposób, w jaki pobiera swoje dane wejściowe, to użycie pop, bez żadnych argumentów. Poza podprogramem popusuwa i zwraca ostatnią wartość, @ARGVktórej jest lista argumentów do programu Perl. Równie łatwo można go zastąpić shift, ale to dodaje kolejne 2 znaki. Zobacz: p3rl.org/pop
Brad Gilbert,
wygląda na to, że potrzebujesz znaku nowej linii w '.', czyli 2 dla \nlub 1, jeśli liczysz spacje w '. '(spacja jest literałem nowej linii)
vol7ron
Trochę dłużej, ale kreatywność w mojej książce jest długa.
Beska
@Platinum Azure et al: Otrzymuje dane wejściowe ze standardowego wejścia. To jest sposób na zrobienie tego w Perlu. (Może zmienił to po twoim komentarzu?)
Frank
@P Daddy: jęk, ale i tak +1 do twojego komentarza
Platinum Azure
30

Common Lisp 157 znaków

Nowa, bardziej zgodna wersja, teraz czytająca ze standardowego wejścia i ignorująca spacje i łączniki:

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

W formie czytelnej dla człowieka:

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

I kilka testów:

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

Oraz wersja bonusowa, przy 165 znakach:

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

Dający

>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
źródło
5
Myślałem, że „dwadzieścia cztery” ma tylko 10 liter?
kennytm
1
Liczby po „jest” również powinny być tekstem.
Mike DeSimone
5
dlaczego to jest tak wysoko? inne nie używają wbudowanej funkcji formatu i mają mniej znaków
Claudiu
3
@Claudiu Ponieważ Common Lisp jest niesamowity.
Mornedhel,
3
Nie ma znaczenia, ile uderzeń wykonasz, jeśli nie dostaniesz piłki do dołka. Wydaje się, że ludzie o tym zapominają, głosując za niewłaściwymi rozwiązaniami.
Mark Peters
21

Python 2.x, 144 150 154 166 znaki

To dzieli liczbę na dziesiątki i jedności i podsumowuje je. Niepożądana właściwość pseudotrójnikowego operatora, a and b or cktóra cjest zwracana, jeśli bwynosi 0, jest tutaj nadużywana.

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

Poprzednia wersja naiwna (150 znaków). Po prostu zakoduj wszystkie długości jako liczby całkowite.

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
źródło
Przepraszam, szczególnie chciałem kropek tylko z powodu takich rzeczy. :-) Ale dobry wpis! (EDIT: Nie wiem, Python, ale można n,"is",p,"."myślę, że jeszcze zaoszczędzić trochę chararacters jeśli liczę prawo?)
Platinum Azure
2
@Plat: To spowodowałoby dodatkową spację przed ..
kennytm
@KennyTM: Och, duh, powinienem to zauważyć nawet po fragmencie. Ups! W każdym razie, jak powiedziałem, niektóre specyfikacje zostały specjalnie zaprojektowane, aby trochę skomplikować. :-)
Platinum Azure
Czy możemy to skrócić, używając podstawy wyższej niż 36?
MikeD,
@MikeD: Nie. Z dokumentacji Pythona: „ Podstawowy parametr określa podstawę konwersji (która domyślnie wynosi 10) i może być dowolną liczbą całkowitą z zakresu [2, 36] lub zerem”. Teraz już może być w stanie wykorzystać funkcję inną niż int(), powiedzmy coś z structlub base64modułów ...
Mike DeSimone
20

C - ze słowami liczbowymi

445 431 427 421 399 386 371 359 * 356 354 348 347 znaków

Otóż ​​to. Nie sądzę, żebym mógł to skrócić.

Wszystkie nowe wiersze są dla czytelności i można je usunąć:

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

Poniżej jest nieco niezmodyfikowany, ale nadal dość trudny do odczytania. Poniżej znajdziesz bardziej czytelną wersję.

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

Rozwinięto i skomentowałem:

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

O zakodowanym napisie na początku

Nazwy liczb są kompresowane przy użyciu bardzo prostego schematu. Często używane podciągi są zastępowane jednoznakowymi indeksami w tablicy nazw. „Tablica przeglądowa” dodatkowych wpisów nazw jest dodawana na końcu dla podciągów nieużywanych w całości w pierwszym zestawie. Odnośniki są rekurencyjne: wpisy mogą odnosić się do innych wpisów.

Na przykład skompresowana nazwa 11 to elM. print()Funkcji generuje znaki ei l(niższy przypadku „L”, a nie liczba „1”) dosłownie, ale nie znajdzie M, więc wymaga się z indeksem pozycji 29 (ASCII „M” - ASCII „0”) do tabeli przeglądowej. Ten ciąg jest evL, więc wyjścia ei v, a następnie zwraca się ponownie z indeksem wejścia 28 w tabeli przeglądowej, która jest en, i jest wyprowadzany dosłownie. Jest to przydatne, ponieważ enjest również używane w eLfor een(używane po eightin eighteen), które jest używane w tOfor teen(używane dla każdej innej -teennazwy).

Ten schemat skutkuje dość znaczną kompresją nazw liczbowych, wymagając jedynie niewielkiej ilości kodu do dekompresji.

Przecinki na początku i na końcu ciągu wyjaśniają uproszczony sposób znajdowania podciągów w tym ciągu. Dodanie tutaj dwóch znaków pozwoli później zaoszczędzić więcej znaków.

O nadużywaniu domeny main()

argvjest ignorowana (i dlatego nie jest zadeklarowana w wersji skompresowanej), wartość argc jest ignorowana, ale pamięć jest ponownie wykorzystywana do przechowywania bieżącej liczby. To po prostu oszczędza mi deklarowania dodatkowej zmiennej.

O braku #include

Niektórzy będą narzekać, że pomijanie #include <stdio.h>jest oszustwem. To wcale nie jest. Podany jest całkowicie legalnym programem w C, który będzie poprawnie kompilował się na dowolnym kompilatorze C, o którym wiem (aczkolwiek z ostrzeżeniami). Z braku protokołów dla funkcji stdio, kompilator założy, że są to funkcje zwracane przez cdecl inti będzie ufał, że wiesz, jakie argumenty przekazać. Zwracane wartości są i tak ignorowane w tym programie i wszystkie są funkcjami cdecl (konwencja wywoływania „C”) i rzeczywiście wiemy, jakie argumenty przekazać.

Wynik

Dane wyjściowe są zgodne z oczekiwaniami:

0
zero to cztery.
cztery to magia.
1
jeden to trzy.
trzy to pięć.
pięć to cztery.
cztery to magia.
4
cztery to magia.
20
dwadzieścia to sześć.
sześć to trzy.
trzy to pięć.
pięć to cztery.
cztery to magia.
21
dwadzieścia jeden to dziewięć.
dziewięć to cztery.
cztery to magia.

* Poprzednia wersja pominęła znak w dwóch częściach specyfikacji: nie obsługiwała zera i pobierała dane wejściowe z wiersza poleceń zamiast stdin. Obsługa zer dodanych znaków, ale użycie stdin zamiast argumentów wiersza poleceń, a także kilka innych optymalizacji pozwoliło zaoszczędzić tę samą liczbę znaków, co spowodowało wyczyszczenie.

Wymagania zostały zmienione, aby wyjaśnić, że słowo numeryczne powinno być drukowane po obu stronach „jest”. Ta nowa wersja spełnia ten wymóg i wprowadza kilka dodatkowych optymalizacji, aby uwzględnić (więcej niż) dodatkowy wymagany rozmiar.

P Tatusiu
źródło
To jest bez wątpienia moje ulubione słowo odpowiedzi ... Brawo, dobra robota. +1 dla ciebie, a gdybym mógł dać dwa znaczniki, zrobiłbym to.
Platinum Azure
5
Fajnie się czyta, myślę, że od teraz będę używał tych liczb w życiu codziennym. Six, sem, eight, nine, tel, elem, twelve, enpee, fourpee, fifpee, sixpee, sevenpee, eightoh, ninepee, twelkyu ... =)
deceze
10

J, 107 112 znaków

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

(Nowy wiersz tylko dla czytelności)

Wykorzystanie i wydajność:

    '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. 
David
źródło
15
Jest opracowany w języku chińskim
Dr. Belisarius
3
Proszę wybrać sędziego spoza Chin
Dr. Belisarius
3
@beli: 멩, 겻, 곋, 멩 to koreański.
kennytm
1
Moja żona (native speaker chiński) mówi, że to mieszanka chińskiego i koreańskiego.
Loren Pechtel
3
@belisarius: 1) Nie zna koreańskiego. 2) Chińczyk to bełkot.
Loren Pechtel
10

T SQL 413 451 499 znaków

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

(Nie, żebym poważnie sugerował, żebyś to zrobił ... naprawdę chciałem tylko napisać CTE)

Używać:

M 95

Zwroty

p                n
----------- ---- -----------
95          is   10.
10          is   3.
3           is   5.
5           is   4.
4 is magic.
Leon Bambrick
źródło
Czy nie możesz po prostu wydrukować poszczególnych wyników zamiast zwracać tabelę? Dzięki temu wyjście wyglądałoby ładniej.
Joey,
1
Nie sądzę, żeby poprawnie obsługiwał zero. Co powiesz na coś takiego: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
Gabe
9

Java (z boilerplate), 308 290 286 282 280 znaków

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

Jestem pewien, że Groovy pozbyłby się wielu z tego.

Wyjaśnienie i formatowanie (wszystkie komentarze, nowe linie i początkowe / końcowe spacje usunięte w liczniku):

Dość proste, ale

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

Edycja: Nie używaj już hex, to mniej naciśnięć klawiszy

Mark Peters
źródło
1
249 bez importu, def class lub main def.
Mark Peters,
1
To diabelskie. Podoba mi się podstawa 16. (+1)
Platinum Azure
Możesz zaoszczędzić jedno miejsce, używając String[]azamiast String[] a.
BalusC,
Dzięki @Balus, również wyeliminowałem grupę, wykonując prostą arytmetykę na znaku, zamiast używać analizy szesnastkowej.
Mark Peters,
@Mark Peters: Jeszcze gorszy. W porównaniu z tym czuję się taka waniliowa.
Platinum Azure,
9

Windows PowerShell: 152 153 184 bajtów

w oparciu o poprzednie rozwiązanie, z większym wpływem innych rozwiązań

$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.'
powodzenia
źródło
Naprawiono obsługę wielokrotności 10 („dziewięćdziesiąt” zamiast „dziewięćdziesiąt zer”).
Gabe
Hej @ Gabe :), dzięki; ostatnio nie miałem zbyt wiele czasu na grę w golfa. Mimo to cudzysłowy $inputmuszą pozostać, ponieważ nie można bezpośrednio rzutować modułu wyliczającego int; działa przy stringpierwszym przejściu :-)
Joey
8

C, 158 znaków

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

(pierwotnie oparty na kodzie Vlada w Pythonie, pożyczył sztuczkę z rozwiązania C ++ Toma Sirgedasa, aby wycisnąć kilka dodatkowych znaków)

wersja rozszerzona:

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.");
}
Ferruccio
źródło
Wydaje się, że nie działa dla mnie: ./magic 10 10 to -27. Usterka segmentacji
Casey
@Casey - wywołanie scanf () było trochę szkicowe. Czytał int w char. Uciekało mi to na OSX i Windows działało, ale zawiesiło się przy wyjściu. Więc ponownie zrobiłem n & c ints. Zdałem sobie sprawę, że mogę porzucić słowo kluczowe int, ustawiając je jako parametry za pomocą notacji K&R. Rezultat jest bezpieczniejszy i krótszy o jeden znak.
Ferruccio
Możesz zaoszczędzić 3 znaki, zastępując „ 466555766” [n / 10] + d [n% 10] -96 na d [n% 10] - „ , +++) ” [n / 10]
Tom Sirgedas
6

Python 129 133 137 148 znaki

Na rozgrzewkę, oto moja pierwsza wersja (poprawia kilka znaków w porównaniu z poprzednim najlepszym Pythonem).

PS. Po kilku redakcjach jest teraz około dwudziestu znaków krótszy:

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.'
Nas Banov
źródło
6

C #: 210 znaków.

Zgnieciony:

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

Rozszerzony:

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

Sztuczki, które wykorzystuje to podejście:

  • Utwórz tabelę przeglądową dla długości nazw numerów na podstawie cyfr pojawiających się w numerze.
  • Użyj wyszukiwania w tablicy znaków w ciągu i arytmetyki znaków zamiast tablicy liczbowej.
  • Użyj aliasów nazw klas jako skrótów Console.doC.
  • ?:Zamiast tego użyj operatora warunkowego (trójargumentowego) ( ) if/else.
  • Użyj \nz Writekodem ucieczki zamiastWriteLine
  • Skorzystaj z faktu, że C # ma zdefiniowaną kolejność oceny, aby umożliwić przypisania wewnątrz Writewywołania funkcji
  • Użyj wyrażeń przypisania, aby wyeliminować dodatkowe instrukcje, a tym samym dodatkowe nawiasy klamrowe
LBushkin
źródło
int[] zbyłby krótszy, ponieważ nie potrzebujenew[]
Joey
Zmieniono, aby używać arytmetyki znakowej zamiast wyszukiwania w tablicy.
LBushkin,
@ mdm20: Masz rację. Wystąpił błąd w tabeli przeglądowej. Naprawiono teraz.
LBushkin,
Cóż, dwunasty raz jest urokiem: * D
LBushkin
Quicky zaoszczędzić 5 znaków: Krótszy niż rzucając "magic"się object, byłoby niejawnie zadzwonić ToString()na ydodając "". Ale, ponieważ +ma wyższy priorytet niż ?:, trzeba umieścić go w prawdziwej części zamiast fałszywej strony: x!=4?y+"":"magic".
P Daddy
6

Perl: 148 znaków

(Perl 233 181 212 206 200 199 198 185 179 149 148 znaków)

  • Przeniesiono skrót wyjątków do tablicy jednostek. Dzięki temu mogłem wyciąć wiele postaci :-)
  • mobrule wskazał na paskudny błąd. Szybka poprawka dodaje 31 znaków, ach!
  • Refaktoryzowany dla zerowego przypadku specjalnego, również do łagodnego golfa.
  • Bezpośredni dostęp do listy do jednorazowego użytku zamiast przechowywania w tablicy? O tak!
  • TAK DUŻO REFACTORING tylko dla JEDNEJ cholernej postaci. To jest naprawdę życie golfisty. :-(
  • Ups, łatwa naprawa białych znaków. 198 teraz.
  • Przywrócono część zbędnego kodu.
  • Ostatnie słowo kluczowe powrotu rjest niepotrzebne, trochę bardziej ogolone.
  • Masowa refaktoryzacja na komentarze; niestety udało mi się uzyskać tylko 149, ponieważ musiałem naprawić błąd, który był obecny zarówno w moim wcześniejszym kodzie, jak iw wersjach komentujących.
  • Próbuję „magii” bez słowa.

Niech ta piłka toczy się skromną próbą w Perlu.

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

Wydziwianie:

Za dużo!

Platinum Azure
źródło
ACK! Jak nigdy nie testowałem, czego nigdy się nie dowiem.
Platinum Azure,
Czy masz tam jakiś martwy kod? Nie rozumiem, jak specjalny przypadek dla zera jest potrzebny, gdy $ u [0] wynosi 4. Mam pozornie działającą wersję twojego kodu @ 166 znaków i myślę, że ma miejsce, aby uzyskać trochę krótszy.
hobbs
@hobbs: Słuszna uwaga, spojrzę jeszcze raz. Historia jest taka, że ​​przeszedłem w połowie przez kilka poprawek i nagle coś się zepsuło (mniej więcej w punkcie, w którym wybrałem 4 -> 0). Myślę, że masz rację w tym momencie :-)
Platinum Azure,
Nie uważam się za wielkiego programistę Perla, ale możesz zredukować niektóre znaki: @u=split$x,'43350435543668877988';twoje przecinki używają niepotrzebnych 19 znaków, dzieląc na undefpodziały przy każdym znaku, używam $xjako niezdefiniowanej zmiennej zastępującej `undef` - total oszczędności: 11 znaków. Usuń również min, chompa otrzymasz kolejną postać ogoloną z twojego wyniku.
vol7ron
Lepiej robi, ale nadal można zaoszczędzić więcej, tracąc sub rcałkowicie - tylko używać go raz i może zastąpić to wszystko przez jednego zagnieżdżonego trójskładnikowego nawet bez parens. Moja wersja jest 144 chars właśnie teraz: gist.github.com/473289
Hobbs
5

JavaScript 1.8 (SpiderMonkey) - 153 znaki

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

Stosowanie: echo 42 | js golf.js

Wynik:

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

Z bonusem - 364 znaki

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

Wynik:

dziewięćdziesiąt dziewięć to dziesięć.
dziesięć to trzy.
trzy to pięć.
pięć to cztery.
cztery to magia.
gnarf
źródło
4

Haskell, 224 270 znaków

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

I trochę bardziej czytelne -

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
źródło
4

Wersja C ++ Stdio, zminimalizowana: 196 znaków

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

Wersja C ++ Iostreams, zminimalizowana: 195 znaków

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

Oryginalny, niezminifikowany: 344 znaki

#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);
}
Karl von Moor
źródło
Naprawiony. To też trochę go skróciło.
Mike DeSimone
Ładnie wykonane. (Dużo się śmiałem z 20-znakowej łamigłówki standardowej!)
Platinum Azure,
Tak, to był prawdziwy headbanger, dopóki nie dotarło do mnie, że #definebyłby jeszcze krótszy, ponieważ mógłby zastąpić kilka żetonów.
Mike DeSimone,
printf("is magic".\n)=> puts. printf("%d",p)=> puts(atoi(p)). Nie tylko krótszy, ale też szybszy.
Ben Voigt,
2
@Mike DeSimone: Myślę, że while(p!=4)można by to skrócić do while(p-4). Wiem, że to jedna postać, ale jednak. :-)
Platinum Azure
3

Delphi: 329 znaków

Wersja z pojedynczą linią:

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.

Sformatowany:

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.

Prawdopodobnie miejsce na trochę ściśnięcia ... :-P

Jørn E. Angeltveit
źródło
3

C # 314 286 283 274 289 273 252 znaków.

Zgnieciony:

252 

Normalna:

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

Edytuj Dykam: Zrobiłem kilka ostrożnych wstawek i zmian:

  • Zmieniono l.ToString () na rzutowanie objectna string "magic".
  • Utworzyłem zmienną tymczasową o, dzięki czemu mogłem przesunąć breakpoza forpętlę, czyli w wyniku czego do-while.
  • Podkreślił oprzypisanie, a także vprzypisanie, kontynuując lcałkowicie wstawianie obliczenia argumentów funkcji, eliminując potrzebę l. Podkreślił również przypisanie m.
  • Usunięto spację w int[] x, int[]xjest też legalna.
  • Próbowałem przekształcić tablicę w transformację ciągów, ale using System.Linqbyło zbyt wiele, aby to poprawić.

Edit 2 Dykam Zmieniono tablicę int na tablicę char / string, dodano odpowiednią arytmię, aby to poprawić.

mdm20
źródło
Tak, jest krótsza niż wersja Java.
Dykam
3

Lua, 176 znaków

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

lub

  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."
gwell
źródło
3

C - bez słów liczbowych

180 175 * 172 167 znaków

Wszystkie nowe wiersze są dla czytelności i można je usunąć:

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

Nieco niezminifikowany:

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

* Poprzednia wersja pominęła znak w dwóch częściach specyfikacji: nie obsługiwała zera i pobierała dane wejściowe z wiersza poleceń zamiast stdin. Obsługa zerowych znaków dodanych, ale użycie stdin zamiast argumentów wiersza poleceń zaoszczędziło jeszcze więcej, co skutkuje oszczędnościami netto.

P Tatusiu
źródło
2

perl, 123 122 znaki

Właśnie zdałem sobie sprawę, że nie ma wymogu wyjścia do STDOUT, więc zamiast tego wyślij do STDERR i zrzuć inny znak.

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

Wersja, która zwraca podane liczby:

279 278 276 280 znaków

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

Chociaż spełnia to specyfikację, nie jest w 100% dobrze sformatowany. Zwraca dodatkową spację po liczbach kończących się na zero. Specyfikacja mówi:

„Nie obchodzi mnie, jak rozdzielasz tokeny słów, chociaż powinny być oddzielone”

To trochę dziwaczne. Bardziej poprawna wersja pod adresem

282 281 279 283 znaków

@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/
cykli user397369
źródło
1

Pyton:

#!/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"
Vlad
źródło
4
Lubię to. Prawdopodobnie mógłbyś to jednak trochę zaostrzyć.
Josh K,
@Vlad: dane wejściowe należy czytać ze standardowego wejścia zamiast z argumentów. Oznacza to, że możesz po prostu użyć N = input()(lub raw_input()) i wyeliminować sysrzeczy.
kennytm
Możesz także sprawić, że smalls będzie zawierać nastolatki, wtedy instrukcja if będzie miała postać „if n <20: return Smalls [n]”. Smalls nadal działałby w przypadku> = 20, ze względu na moduł o wartości 10.
Jon Smock,
5
To chyba pierwszy raz, kiedy widzę (całkowicie opcjonalne) she-bangw odpowiedzi na golfa kodowego ;-)
ChristopheD
Wygląda na dobry początek ... Zdecydowanie sprecyzuj, nawet Python nie potrzebuje WSZYSTKICH tych białych znaków. :-) Ponadto, jak zauważa Ferruccio, 0 nie działa, a konkretnie wydaje się wchodzić w nieskończoną pętlę.
Platinum Azure,
1

C ++, 171 znaków (# Uwzględnij pominięte)

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.");}
Tom Sirgedas
źródło
Myślę, że jeśli uznasz to za C, możesz uniknąć potrzeby, #includeponieważ zakłada się, że funkcje przyjmują intparametry. Możesz nawet zapisać pociągnięcie, wykonując mainpowrót int.
Gabe,
1

Ruby, 164 znaki

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

dekodowane:

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."
Jon Smock
źródło
Ładne rozwiązanie Ruby, proste. :-) (+1)
Platinum Azure
Utrzymywanie tego w prostocie nie jest jednak wymówką dla zbyt długiego trzymania się ;-)
Joey,
Myślę, że możesz zamienić „if n == 0” na „if! N”
Vincent,
2
W Rubim? Zawsze myślałem, że wszystkie wartości oprócz false i nil są oceniane na true :-(
Platinum Azure
1

Lua 185 190 199

dodane kropki, dodane io.read, usunięte () przy ostatnim wydruku

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

ze znakami końca linii

 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.'
Nick
źródło
Potrzebuje n=io.read()znaku (+11 znaków), aby zachować zgodność z regułą odczytu liczby ze standardowego wejścia. Zmiana print('4 is magic.')na print'4 is magic.'zapisze 2 znaki. Usunięcie ;po )zapisuje 1 znak. Do printpomocą przecinków Wygląda na to oszustwo, ale specyfikacja jest niejasna. Równie dobrze możesz to zmienić, print(n,'is',m,'.')aby zapisać 2 znaki.
gwell
Czy przecinki są renderowane jako znaki nowej linii w Lua samodzielnie? Minęło trochę czasu, odkąd go używałem.
Nick Van Brunt,
Przecinki są renderowane jako tabulatory.
gwell
0

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

//////////// testing ////////////////

 $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';
    }

////// Wyniki /////////

Twelve =6
Six =3
Three =5
Five =4
four is magic
Deweloper
źródło
4
@wallacoloo: kiepskie rozwiązanie dla kiepskiego języka: D
Thomas Eding,
5
Lub znacznie krótsze 178 znaków:$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
Ładny żart. :-D Tak dobrze zaprogramowany.
Tom Pažourek,
0

Perl - 130 znaków


5.12.1 (130 znaków) 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 znaków) 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/


Zmieniać historię:

20100714:2223- cofnięto zmianę, na którą zwróciła uwagę mobrule , ale ($_%10&&$u[$_%10])(($_%=10)&&$u[$_]), czyli ta sama liczba znaków, ale zrobiłem to na wypadek, gdyby ktoś mógł zobaczyć sposób na jej poprawę

20100714:0041- split//,'...''...'=~/./g
20100714:0025- ($_%10&&$u[$_%10])$u[$_%10]
20100713:2340- while$_until/\D/+ usunięto niepotrzebne nawiasy
20100713:xxxx- $=<>;chop;$_=pop;- dzięki uprzejmości mobrule


Uwaga: byłem zmęczony poprawianiem odpowiedzi innych w komentarzach, więc teraz jestem chciwy i mogę po prostu dodać tutaj swoje zmiany :) To jest oddzielenie od odpowiedzi Platinum Azure - zasługa częściowo Hobbs , mobrule i Platinum Azure .

vol7ron
źródło
Kiedy pozbyłeś się $_%10&&...konstruktu, złamałeś specyfikację dla wejść 20,30,40, ...
mob
+1 Świetnie. Jednak wyszedłeś ze stdin na argumenty :-(
Platinum Azure
Tak, zastąpione przez ARGV, które jest wypełniane przez STDIN:) lub .. echo bar | xargs perl foo.pl, technicznie przesyłane z echa do argumentów dla perla :)
vol7ron.
0

Shameless Perl with Number Words (329 znaków)

Zaadaptowany dość bezpośrednio z kodu C P Daddy'ego, z kilkoma poprawkami, aby p()robił to samo, używając prymitywów Perla zamiast C i przeważnie przepisanej pętli głównej. Zobacz jego wyjaśnienie. Nowe linie są opcjonalne.

@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

Na marginesie: szkoda, że ​​perl printpo prostu zwraca prawdę / fałsz; gdyby zwrócił liczbę, zaoszczędziłoby mi 7 uderzeń.

hobbów
źródło
0

Ruby, 141 znaków:

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}
Krzysztof
źródło
-7
while(true)
{
    string a;
    ReadLine(a)
    WriteLine(4);

}
user368038
źródło