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:
- Rozwiązania muszą być kompletnymi programami same w sobie. Nie mogą być po prostu funkcjami, które przyjmują liczbę - czynnik w danych wejściowych.
- 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)
- Dane wejściowe powinny mieć postać liczbową.
- Dla każdego zastosowania funkcji transformacji należy wydrukować wiersz:,
a is b.
gdzie a i b są liczbowymi postaciami liczb w transformacji. - Wymagane są kropki (okresy)!
- Ostatnia linia powinna naturalnie powiedzieć
4 is magic.
. - 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ń:
- Chcę, aby słowo pojawiało się po obu stronach we wszystkich odpowiednich przypadkach, np
Nine is four. Four is magic.
- Nie obchodzi mnie jednak kapitalizacja. I nie obchodzi mnie, jak rozdzielasz tokeny słów, chociaż powinny być oddzielone:
ninety-nine
jest w porządku,ninety nine
jest w porządku,ninetynine
nie 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.
źródło
Odpowiedzi:
GolfScript -
10196939291909486 bajtów90 → 94
: Naprawiono wynik dla wielokrotności 1094 → 86
.: Zrestrukturyzowany kod. Używanie podstawy 100 do usuwania znaków niedrukowalnych.86 → 85
: Krótszy rzut na strunę.źródło
"magic."
, to właściwie podsumowuje.d
jest wyodrębniany przez)
as100
i używany jako podstawa konwersji podstawowej.Perl, około 147 znaków
Luźno oparty na rozwiązaniu Platinum Azure:
źródło
pop
, bez żadnych argumentów. Poza podprogramempop
usuwa i zwraca ostatnią wartość,@ARGV
któ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'.'
, czyli 2 dla\n
lub 1, jeśli liczysz spacje w'. '
(spacja jest literałem nowej linii)Common Lisp 157 znaków
Nowa, bardziej zgodna wersja, teraz czytająca ze standardowego wejścia i ignorująca spacje i łączniki:
W formie czytelnej dla człowieka:
I kilka testów:
Oraz wersja bonusowa, przy 165 znakach:
Dający
źródło
Python 2.x, 144
150154166znakiTo dzieli liczbę na dziesiątki i jedności i podsumowuje je. Niepożądana właściwość pseudotrójnikowego operatora,
a and b or c
którac
jest zwracana, jeślib
wynosi 0, jest tutaj nadużywana.Poprzednia wersja naiwna (150 znaków). Po prostu zakoduj wszystkie długości jako liczby całkowite.
źródło
n,"is",p,"."
myślę, że jeszcze zaoszczędzić trochę chararacters jeśli liczę prawo?).
.int()
, powiedzmy coś zstruct
lubbase64
modułów ...C - ze słowami liczbowymi
445431427421399386371359 *356354 †348347 znakówOtóż 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 znakie
il
(niższy przypadku „L”, a nie liczba „1”) dosłownie, ale nie znajdzieM
, więc wymaga się z indeksem pozycji 29 (ASCII „M” - ASCII „0”) do tabeli przeglądowej. Ten ciąg jestevL
, więc wyjściae
iv
, a następnie zwraca się ponownie z indeksem wejścia 28 w tabeli przeglądowej, która jesten
, i jest wyprowadzany dosłownie. Jest to przydatne, ponieważen
jest również używane weL
foreen
(używane poeight
ineighteen
), które jest używane wtO
forteen
(używane dla każdej innej-teen
nazwy).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()
argv
jest 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 cdeclint
i 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:
* 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.
źródło
J, 107
112znaków(Nowy wiersz tylko dla czytelności)
Wykorzystanie i wydajność:
źródło
T SQL 413
451499znaków(Nie, żebym poważnie sugerował, żebyś to zrobił ... naprawdę chciałem tylko napisać CTE)
Używać:
Zwroty
źródło
CREATE FUNCTION d(@ int) RETURNS int AS BEGIN Declare @l char(9),@s char(50) Select @l='066555766',@s='03354435543668877987' if @=0 return 4 if @<20 return 0+substring(@s,@+1,1)return 0+substring(@l,@/10,1)+substring(@s,@%10+1,1)END
Java (z boilerplate),
308290286282280 znakówJestem 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
Edycja: Nie używaj już hex, to mniej naciśnięć klawiszy
źródło
String[]a
zamiastString[] a
.Windows PowerShell: 152
153184bajtóww oparciu o poprzednie rozwiązanie, z większym wpływem innych rozwiązań
źródło
$input
muszą pozostać, ponieważ nie można bezpośrednio rzutować modułu wyliczającegoint
; działa przystring
pierwszym przejściu :-)C, 158 znaków
(pierwotnie oparty na kodzie Vlada w Pythonie, pożyczył sztuczkę z rozwiązania C ++ Toma Sirgedasa, aby wycisnąć kilka dodatkowych znaków)
wersja rozszerzona:
źródło
Python 129
133137148znakiNa 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:
źródło
C #: 210 znaków.
Zgnieciony:
Rozszerzony:
Sztuczki, które wykorzystuje to podejście:
Console.
doC.
?:
Zamiast tego użyj operatora warunkowego (trójargumentowego) ( )if/else
.\n
zWrite
kodem ucieczki zamiastWriteLine
Write
wywołania funkcjiźródło
int[] z
byłby krótszy, ponieważ nie potrzebujenew[]
"magic"
sięobject
, byłoby niejawnie zadzwonićToString()
nay
dodając""
. Ale, ponieważ+
ma wyższy priorytet niż?:
, trzeba umieścić go w prawdziwej części zamiast fałszywej strony:x!=4?y+"":"magic"
.Perl: 148 znaków
(Perl
233181212206200199198185179149148 znaków)r
jest niepotrzebne, trochę bardziej ogolone.Niech ta piłka toczy się skromną próbą w Perlu.
Wydziwianie:
Za dużo!
źródło
@u=split$x,'43350435543668877988';
twoje przecinki używają niepotrzebnych 19 znaków, dzieląc naundef
podziały przy każdym znaku, używam$x
jako niezdefiniowanej zmiennej zastępującej `undef` - total oszczędności: 11 znaków. Usuń równieżm
in,chomp
a otrzymasz kolejną postać ogoloną z twojego wyniku.sub r
cał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/473289JavaScript 1.8 (SpiderMonkey) - 153 znaki
Stosowanie:
echo 42 | js golf.js
Wynik:
Z bonusem - 364 znaki
Wynik:
źródło
Haskell, 224
270znakówI trochę bardziej czytelne -
źródło
Wersja C ++ Stdio, zminimalizowana: 196 znaków
Wersja C ++ Iostreams, zminimalizowana: 195 znaków
Oryginalny, niezminifikowany: 344 znaki
źródło
#define
byłby jeszcze krótszy, ponieważ mógłby zastąpić kilka żetonów.printf("is magic".\n)
=>puts
.printf("%d",p)
=>puts(atoi(p))
. Nie tylko krótszy, ale też szybszy.while(p!=4)
można by to skrócić dowhile(p-4)
. Wiem, że to jedna postać, ale jednak. :-)Delphi: 329 znaków
Wersja z pojedynczą linią:
Sformatowany:
Prawdopodobnie miejsce na trochę ściśnięcia ... :-P
źródło
C #
314286283274289273252 znaków.Zgnieciony:
Normalna:
Edytuj Dykam: Zrobiłem kilka ostrożnych wstawek i zmian:
object
nastring
"magic"
.o
, dzięki czemu mogłem przesunąćbreak
pozafor
pętlę, czyli w wyniku czegodo-while
.o
przypisanie, a takżev
przypisanie, kontynuującl
całkowicie wstawianie obliczenia argumentów funkcji, eliminując potrzebęl
. Podkreślił również przypisaniem
.int[] x
,int[]x
jest też legalna.using System.Linq
było zbyt wiele, aby to poprawić.Edit 2 Dykam Zmieniono tablicę int na tablicę char / string, dodano odpowiednią arytmię, aby to poprawić.
źródło
Lua, 176 znaków
lub
źródło
C - bez słów liczbowych
180175*172167 znakówWszystkie 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.
źródło
perl,
123122 znakiWł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.
Wersja, która zwraca podane liczby:
279278276280 znakówChociaż spełnia to specyfikację, nie jest w 100% dobrze sformatowany. Zwraca dodatkową spację po liczbach kończących się na zero. Specyfikacja mówi:
To trochę dziwaczne. Bardziej poprawna wersja pod adresem
282281279283 znakówźródło
Pyton:
źródło
N = input()
(lubraw_input()
) i wyeliminowaćsys
rzeczy.she-bang
w odpowiedzi na golfa kodowego ;-)C ++, 171 znaków (# Uwzględnij pominięte)
źródło
#include
ponieważ zakłada się, że funkcje przyjmująint
parametry. Możesz nawet zapisać pociągnięcie, wykonującmain
powrótint
.Ruby, 164 znaki
dekodowane:
źródło
Lua
185190199dodane kropki, dodane io.read, usunięte () przy ostatnim wydruku
ze znakami końca linii
źródło
n=io.read()
znaku (+11 znaków), aby zachować zgodność z regułą odczytu liczby ze standardowego wejścia. Zmianaprint('4 is magic.')
naprint'4 is magic.'
zapisze 2 znaki. Usunięcie;
po)
zapisuje 1 znak. Doprint
pomocą 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.Kod PhP
//////////// testing ////////////////
////// Wyniki /////////
źródło
$l='4335443554366887798866555766';for($b=(int)fgets(fopen('php://stdin','r'));($a=$b)-4;){$b=$a<20?$l[$a]:$l[18+$a/10]+($a%10?$l[$a%10]:0);echo"$a is $b.\n";}echo"4 is magic.\n";
Perl - 130 znaków
5.12.1 (130 znaków)
1211231321361405.10.1 (134 znaków)
125127136140144Zmieniać 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 nawiasy20100713:xxxx
-$=<>;chop;
→$_=pop;
- dzięki uprzejmości mobruleUwaga: 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 .
źródło
$_%10&&...
konstruktu, złamałeś specyfikację dla wejść 20,30,40, ...ARGV
, które jest wypełniane przezSTDIN
:) lub ..echo bar | xargs perl foo.pl
, technicznie przesyłane z echa do argumentów dla perla :)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.Na marginesie: szkoda, że perl
print
po prostu zwraca prawdę / fałsz; gdyby zwrócił liczbę, zaoszczędziłoby mi 7 uderzeń.źródło
Ruby, 141 znaków:
źródło
źródło