Jako dane wejściowe podano dwa ciągi reprezentujące dodatnie liczby całkowite w bazie 10, takie jak "12345"
i "42"
. Twoim zadaniem jest "518490"
w tym przypadku wyprowadzenie ciągu zawierającego ich produkt .
Rzecz w tym, że nie możesz używać żadnych typów numerycznych w swoim kodzie. Nie ints
, float
s, unsigned long
s itp., Brak wbudowanych typów liczb zespolonych, liczb całkowitych o dowolnej dokładności lub cokolwiek wzdłuż tych linii. Wielu z was nie używa literałów tego typu ani żadnej funkcji, metody, operatora itp., Która je zwraca.
Państwo może używać ciągi, wartości logicznych, tablic, ani niczego innego, co normalnie nie być używane do reprezentowania numer. (Należy jednak pamiętać, że ani indeksowanie do tablicy, ani uzyskanie jej długości prawdopodobnie nie będzie możliwe bez wywołania typu liczbowego.) char
S są dozwolone, ale nie można wykonywać na nich żadnych operacji arytmetycznych lub bitowych ani w żaden inny sposób traktować ich jako niczego innego niż token reprezentujący część ciągu. ( char
Dozwolone jest porównanie leksykograficzne s.)
Nie możesz obejść tego ograniczenia. Obejmuje to (ale nie wyłącznie) używanie typów numerycznych w eval
funkcji typu, niejawne konwersje typów na typy numeryczne, stosowanie operatorów numerycznych lub bitowych na typach nienumerycznych, które je obsługują, używanie typów numerycznych przechowywanych w typach kontenerów lub wywoływanie funkcji lub programy zewnętrzne, które zwracają wyniki liczbowe w postaci łańcucha. (Zastrzegam sobie prawo do dodania do tej listy, jeśli w odpowiedziach pojawią się inne obejścia). Musisz samodzielnie zaimplementować mnożenie, używając tylko typów nienumerycznych.
Wejście i wyjście może odbywać się dowolną dogodną metodą, o ile dane wchodzą i wychodzą z kodu w postaci ciągu. Możesz założyć, że każdy z dwóch argumentów wejściowych zawiera tylko znaki ASCII [0-9]
i nie zacznie się od 0
. Twój wynik również nie powinien mieć wiodących zer.
Jeszcze jedno: twój kod musi poprawnie obsługiwać dane wejściowe o długości co najmniej 10 znaków i musi działać w niecałą minutę na nowoczesnym komputerze dla wszystkich danych wejściowych w tym zakresie. Przed wysłaniem sprawdź, czy po podaniu danych wejściowych 9999999999
i 9999999999
program daje wynik 99999999980000000001
w ciągu mniej niż minuty. To ograniczenie istnieje specjalnie po to, aby zapobiec odpowiedziom, które przydzielają tablicę rozmiarów, a*b
a następnie iterują nad nią, więc pamiętaj, że odpowiedzi tego formularza nie będą mogły wygrać.
To jest golf golfowy , więc wygrywa najkrótsze prawidłowe rozwiązanie (w bajtach).
źródło
"12345"
zamiast STDIN12345
? Czy możemy zaakceptować obie liczby jako"12345", "42"
?m
in
i powrocie argument długościm*n
. Ale ponieważ ciągi muszą dosłownie zawierać reprezentację liczb ASCII, myślę, że jest to niezgodne z regułami.a,b="0123456789x".split('0');c=iter(b).next()
if c=='x':
c='0'
a,b="0123456789x".split(x);c,*d=b
if c=='x':
c='0'
d='123456789';I=dict(zip('0'+d,d+'0'))
Odpowiedzi:
Haskell - 180
206 214Wprowadza mnożenie poprzez wielokrotne dodawanie, a wszystkie rodzaje cyfrowej magii są obsługiwane przez przesuwanie i filtrowanie
['0'..'9']
listy. Definiuje operator#
typuString -> String -> String
:źródło
"0123456789"
jest listą['0'..'9']
. Po drugie, w Haskell [a..b] znajduje się wyliczenie, typy, które zadeklarowały wystąpieniaEnum
klasy, mogą być wyliczone w ten sposób, a deklaracja opisuje sposób działania wyliczenia.Bool
, typ boolowski ma również instancję, dlatego możesz to zrobić[False..True]
. Nie ma w tym prawie żadnych liczb.sed,
339338 bajtówWiem, że to stary, ale przeglądałem i to wzbudziło moje zainteresowanie. Wystarczy, aby zarejestrować się jako użytkownik! Chyba zachwyciło mnie „ Chciałbym zobaczyć pełne rozwiązanie sed - Nathaniel ” ...
Ten skrypt sed oczekuje na wejściu dwóch liczb dziesiętnych oddzielonych jedną spacją
testy:
Dwa ostatnie można rozpoznać jako RSA-100 (50 x 50 cyfr) i RSA-768 (116 x 116 cyfr).
Używając GNU sed na niezbyt nowoczesnym (Intel Core 2 z ery 2007), ostatni z nich zajmuje ponad minutę, ale na nowszym procesorze jest szybszy:
Niewielki 10-cyfrowy mnożnik określony w pytaniu zajmuje dokładnie jedną sekundę na dowolnym z nich (pomimo tego, że jest pełen patologicznych dziewiątek).
Uważam, że jest to standardowy sed, bez rozszerzeń. POSIX gwarantuje, że pomieści tylko 8192 bajtów, co ogranicza nas do pomnożenia liczb 400 x 400 cyfr, ale implementacje mogą zapewnić więcej. GNU sed jest ograniczony tylko dostępną pamięcią, więc może zarządzać czymś znacznie większym, jeśli chcesz poczekać.
I jestem pewien, że przestrzegałem zasad - to prawie dane w języku, który nie ma liczb. :-)
Wyjaśnienie
Korzystam z hybrydowej jedności / dziesiętnej, przekształcając liczby dziesiętne w sekwencję jedności:
W jednostkowym ułamku dziesiętnym dodawanie jest łatwe. Iterujemy od najmniej znaczącej do najbardziej znaczącej cyfry, łącząc x:
Następnie usuwamy białe znaki i zajmujemy się przenoszeniem, konwertując 10 kolejnych x na jedną z następnych jednostek:
Po dodaniu możemy pomnożyć. Mnożymy x * y przez ostatnią cyfrę y. Dodaj x do akumulatora wiele razy, a następnie przejdź do następnej cyfry i przesuń x jedno miejsce po przecinku w lewo. Powtarzaj, aż y wyniesie zero.
Rozszerzony kod
źródło
sed, 379 bajtów
Podziękowania za tę świetną odpowiedź należą się dla @LuigiTiburzi w systemach Unix i Linux.SE: https://unix.stackexchange.com/a/37213/34061 . Kilka dni temu natknąłem się na to:
Ogólne wyjaśnienie
12*3
staje<1<2*<3
|
znaków. Tak się<1<2*<3
staje<|<||*<|||
|<
ze<||||||||||
w celu przesunięcia wyższych miejsc po przecinku wszystko w dół do pozycji jednostek. Tak się<|<||*<|||
staje<||||||||||||*<|||
<
. Tak się<||||||||||||*<|||
staje||||||||||||*|||
|
z RHS*
. Tak się||||||||||||*|||
staje||||||||||||*||
|
w RHS na wszystkie|
w LHS. Ma to efekt mnożenia liczby LHS i RHS w|
otrzymując Produkt Liczba|
Zatem||||||||||||*||
staje||||||||||||||||||||||||||||||||||||*
*
. Tak się||||||||||||||||||||||||||||||||||||*
staje||||||||||||||||||||||||||||||||||||
|
wstecz na dziesiętną przez odwrócenie pierwszych kilku kroków. Tak się||||||||||||||||||||||||||||||||||||
staje36
.Wydajność:
Niestety nie udaje mu się to z powodu wymaganego czasu -
200*1000
trwa 41 sekund na mojej maszynie Wirtualnej Ubuntu, a środowisko wykonawcze wydaje się iść w górę z kwadratem produktu końcowego.źródło
length()
co zwraca liczbę. Ten używa wyłącznie podstawienia wyrażeń regularnych bez typów liczbowych. Myślę, że twoja odpowiedź jest potencjalnie zwycięzcą, jeśli możesz usunąćlength()
- może zamiast tego możesz wykonać podobne podstawienie wyrażenia regularnego?Python -
312286273Jeśli dozwolone jest (wiele) wiodących zer, ostatnie 12 znaków nie jest potrzebne.
To zasadniczo wykonuje ręczne pomnożenie. Cyfry są reprezentowane jako ciągi powtarzających się
I
s (jak prymitywne cyfry rzymskie). Liczby są reprezentowane jako listy cyfr w odwrotnej kolejności. Dodawanie pojedynczych cyfr odbywa się przez kokatenowanie łańcuchów i usunięcie dziesięciuI
s, jeśli to konieczne.Oto wersja bez golfa:
źródło
def A(x,y):\n S=[];o=""
->def A(x,y,S=[],o=""):
. Niestety,["","1"][t in i]
nie jest dozwolone; używa indeksu bool, traktując go jako liczbę. Myślę jednak, że tot in i and"1"or""
powinno zadziałać.S
jako argument z wartością domyślną nie zadziałałoby, ponieważ zawsze byłaby to ta sama lista nawet dla różnych wywołań funkcji, a zatem nie resetuje się do[]
. Miałeś rację["","1"][t in i]
, naprawiłem to. Dodałem także wyjaśnienie.Rubin:
752698To tylko po to, aby uzyskać odpowiedź, zrobioną z ciekawości. Edytowane: teraz trochę golfa.
Zastosowanie: Miałem to w pliku o nazwie peasant.rb:
Wyjaśnienie: to rozmnażanie wieśniaków, więc wielokrotnie zmniejszam o połowę i podwajam. Przekrawanie odbywa się poprzez zmniejszenie o połowę cyfr i zaznaczenie pozostałych: 1234 -> 0b1a1b2a; następnie znajdź i zamień na b: 06a17a; następnie sprzątanie -> 617.
Dodawanie odbywa się w ten sposób ... po pierwsze, podbijam oba ciągi na tej samej długości i tworzę pary z cyfr. Następnie dodaję cyfry, konstruując ciąg o długości każdej cyfry i łącząc; Usuwam ciąg o tej długości z początku „0123456789abcdefghij”, a następnie zachowuję pierwszy znak. Na przykład „9” + „9” -> „i”. Uwaga: Unikam tutaj używania funkcji długości, aby całkowicie uniknąć typów liczb; usunięcie prefiksu odbywa się za pomocą wyrażenia regularnego.
Więc teraz mam ciąg zawierający mieszankę cyfr i liter. Litery oznaczają cyfry z cyfrą przeniesienia; Wprowadzam 0 do liczby, a następnie wielokrotnie zastępuję wzorce cyfr i liter wynikiem wyniku przenoszenia, aż dodawanie zostanie zakończone.
źródło
Brainfuck (1328 bajtów)
Rozważania na początku:
Program przetestowałem tylko z moim własnym tłumaczem, można go znaleźć tutaj .
Dane wejściowe muszą być liczbami oddzielonymi pojedynczą spacją ASCII.
Gra w golfa:
Nie golfowany:
Dzięki autorowi wziąłem kod wyjściowy wartości z tej odpowiedzi !
Program może nie być prawidłowy, ale w każdym razie chciałem się z tobą podzielić ^^
Aktualizacja: Teraz można przetestować (tylko dla małych mnożenia) tutaj, dzięki @ SP3000 za odpowiedzi do tego konkursu i nowe Snippets Stos SE!
źródło
Python,
394349340 znakówDziałaj jak:
Trwa 50 milisekund.
Wykorzystuje rozmnażanie rosyjskiego chłopa . Podczas dodawania cyfr przekształcamy je w jednoargumentowe („5” => [R, R, R, R, R]), łączymy listy, a następnie przekształcamy z powrotem.
U
konwertuje na unarny, używającR
jako cyfry unarnej. Obliczamyb/=2
jakob=b*5/10
.źródło
def A(a,b):\n r='';c=[]
->def A(a,b,r='',c=[]):
, podobnie dladef M
. Możesz być w stanie zmienićfor z in D:d.pop()\n c=['X']
na[d.pop()for z in D];c=['X']
, w którym to przypadku możesz nawet zwinąć go do poprzedniegoif
. Ponadto możeif list(b).pop()in'13579'
być po prostuif b[:].pop()in'13579'
?b
jest ciągiem, a nie listą.M
i napisać pełny program;a,b=input()
jest dozwolone.reduce
, co pozwala ci naA(b,A(b,A(b,A(b,b))))
toreduce(A,[b,b,b,b,b])
. Niestety nie wpływa to na liczbę postaci.JavaScript (E6) 375
395 411 449Edycja golfed
Edit buga: brak rozliczeń flagę carry
Można to zrobić za pomocą manipulacji symbolami w czasie prawie 0.
W tej wersji możesz użyć dowolnego znaku zamiast cyfr, o ile symbol jest w porządku rosnącym.
Uwagi: używanie ciągów, mapa skrótów z kluczem ciągu, tablice używane jako lista. Bez indeksowania, tablice są przesuwane za pomocą „mapy” lub obracane za pomocą push & shift.
Wszystkie znaki „+” są łączeniem łańcuchowym.
Mniej gra w golfa (może jutro dodam wyjaśnienie)
Testuj w konsoli FireFox / FireBug
Wydajność
źródło
9999999999
powinien być99999999980000000001
, a nie99999999980000000081
Haskell, 231 bajtów
Definiuje to operator #, który zwielokrotnia dwa ciągi znaków liczb naturalnych. Działa poprzez zdefiniowanie elementarnej operacji zwiększania / zmniejszania ciągów, a następnie wykorzystuje ją do budowania dodawania i mnożenia. Trochę dodatkowej magii daje wykładnicze przyspieszenia, które sprawiają, że wszystko jest możliwe ...
To podejście jest na tyle szybkie, że nawet na laptopie z 2008 roku w niezoptymalizowanym ghci REPL przypadek testowy zajmuje zaledwie ułamek sekundy:
Oto sprawdzenie, czy wszystkie dwucyfrowe produkty są poprawne:
źródło
Bash + ImageMagick: 52
Oczekuje, że dane wejściowe będą w zmiennych powłoki
a
ib
. Nie jest to szczególnie sprytne ani wydajne, ale wykonuje zadanie. Prawdopodobnie zostało to zrobione wcześniej.Zauważ, że
x
oznacza wymiary obrazu; w tym kontekście nie jest operatorem arytmetycznym.Nie testowałem tego, ale jestem gotów założyć, że w przypadku nie-ekstremalnych danych wejściowych, zakończy się ono w niecałą minutę. Mogę to przetestować jutro.
W przypadku jakiejkolwiek śmiesznej firmy z wersjami ImageMagick, używam tej:
ImageMagick 6.7.7-10
źródło
9999999999
i9999999999
.dd if=/dev/zero bs=$a count=$b 2>&-|wc -c
.9999999999x9999999999
Obraz w formacie 8bit zajmie wszystkie miejsca na dysku twardym, że obecnie istnieje na Ziemi. Oczywiście png byłby znacznie mniejszy, jeśli można go utworzyć bez uprzedniego utworzenia surowego obrazu. (Chociaż mocno podejrzewam, że miałbyś problemy z przepełnieniem liczb całkowitych w przypadku obrazu o takim rozmiarze). Mimo to, taka metoda prawie na pewno nie działałaby z powodu luki w nazywaniu rzeczy, które zwracają wyniki liczbowe.$b
zamiast${b}
.grep -vc g
zamiastgrep -v g|wc -l
.Python 2 (dowód koncepcji)
To rozwiązanie działa tylko przy użyciu ciągów i list oraz małego wyrażenia regularnego. Uważam, że pasuje to całkowicie do specyfikacji, z tym, że nie da się tego zrobić
9999999999x9999999999
w ciągu minuty. Mimo wystarczającej ilości czasu to zadziała. Może dość szybko pomnożyć 4 cyfry.Ponieważ jest to technicznie nieważne, nie zadałem sobie trudu, aby całkowicie go zagrać w golfa. Zrobię to, jeśli zasady się zmienią.
Przykłady:
źródło
Python 2 (555)
Normalnie nie odpowiedziałbym tak szybko (lub wcale) na własne wyzwanie, ale chciałem udowodnić, że da się to zrobić. (Na szczęście niektóre inne odpowiedzi zrobiły to wcześniej, ale nie mogłem powstrzymać się od chęci ukończenia go.) Jest jeszcze trochę golfa, które można zrobić, ale myślę, że jest to uzasadnione. Obsługuje
9999999999x9999999999
skrzynkę na moim komputerze w czasie poniżej 0,03 sekundy.Przykładowe zastosowanie:
m("12345","42")
Działa poprzez długie mnożenie za pomocą manipulacji ciągiem. Czasami zmienne są ciągami, a czasem iteratorami po ciągach, co umożliwia uzyskanie pierwszego elementu bez użycia literału całkowitoliczbowego. Wszystko jest przechowywane z odwróconymi cyframi, dzięki czemu pierwszy element jest najmniej znaczącą cyfrą.
Oto objaśnienie funkcji po funkcji:
r
is
są funkcjami księgowymi. (r
to tylko alias dlareversed
, który tworzy iterator zwrotny is
konwertuje iteratory na ciągi znaków).i
zwiększa liczbę w ciągu o 1, włączając przypadki takie jak39+1=40
i99+1=100
.b
dodajex
iy
, aley
musi być tylko jedną cyfrą. Działa poprzez zwiększeniex
y
czasu.a
dodaje dwie liczby razem, które mogą mieć wiele cyfr, dzwoniącb
dla każdej cyfry wy
.n
mnożyx
iy
, aley
musi być tylko jedną cyfrą. Działa, dodającx
do siebiey
czasy.o
mnożyx
iy
, gdy oba argumenty mogą mieć wiele cyfr. Wykorzystuje klasyczne długie mnożeniem
po prostu konwertuje wejściowe ciągi znaków na odwrotne iteratory i podaje jeo
, a następnie odwraca wynik i konwertuje je na ciąg znaków.źródło
def a(x,y):
->def a(x,y,z=''):
i usuń następną linię; Podobne sztuczki dla innych zadań,def o(x,y):
zmieńx=s(x)
sięx=s(x);l='';z=''
, że dla pętli, podobnie usunąć nowalinia + kroków; zamiast tego użyj;
. Myślę też, żeif h!='0':h+=s(x)\nelse:h+=i(x)
może po prostu byćh+=h!='0'and i(x)or s(x)
; może naweth+=(h!='0'and i or s)(x)
; w przeciwnym razie po prostu zmień naif'0'!=h
. Także rzeczy takie jakdef r(x):return reversed(x)
->r=reversed
s
,m
:s=lambda x:''.join(x)
,m=lambda x,y:s(r(o(r(x),r(y))))
zamiast całej deklaracji funkcji. Dzięki tym, co wiem, działa, to zmniejsza liczbę bajtów do 521.for
pętli:for c in'0'+d:\nif c==y:break\nz=a(iter(z),x)
->for c in'0'+d:\nif c!=y:z=a(iter(z),x)
, chociaż może to znacznie zmienić szybkość twojego programu.JavaScript:
37103604 bajtówGolf:
Niepoddane testom:
To daje:
źródło
Haskell
507496Działa to dla dowolnie dużych liczb całkowitych. Definiuję niestandardowe reprezentacje liczb naturalnych od 0 do 18 (największa liczba naturalna równa sumie dwóch cyfr) i definiuję mnożenie endianu za pomocą mnożenia cyfr * liczby, które definiuję pod względem liczby + dodawania liczb , które definiuję w kategoriach cyfry + dodawania cyfr. Mam funkcję redukcji, która rozszerza wartości 10-18 na ich cyfrowy rozkład. To po prostu czyta i odwraca dwa ciągi, tłumaczy na niestandardowe wiązania, mnoży i tłumaczy z powrotem, odwracając, aby uzyskać właściwy wynik.
Edytuj 2
Zapisałem kilka znaków, tworząc krótkie lokalne aliasy dla poleceń wieloznakowych, których używam więcej niż jeden raz, a także usuwając spacje i nawiasy oraz zastępując
(
-)
parami,$
jeśli to możliwe.Dla porównania, S jest niestandardowym typem danych typu całkowitoliczbowego,
p
to „plus” (cyfra + dodanie cyfry),s
jest odejmowanie (w celu zmniejszenia),r
jest zmniejszane (rozszerzanie do rozkładu cyfrowego),a
to dodawanie (liczba + dodawanie liczb),m
to mnożyć (mnożenie cyfry * liczby),t
to razy (mnożenie liczby * liczby),i
to „interpretować” (konwertować ciąg znaków na listęS
),b
to „wstecz” (lista S na ciąg znaków), a f i g to tylko skróty do gry w golfa cele. Nie użyłem liczb, nawet domyślnie; najbliższe mi było użycie następców i poprzedników, które są koncepcjami matematycznymi na wyższym poziomie niż dodawanie i mnożenie liczb naturalnych.Edytować
Zapomniałem dołączyć profil czasowy.
Na wszelki wypadek:
Chodźmy szaleni!
potwierdzenie
źródło
Python 2 -
1165, 712, 668664Zauważ, że nie używam logicznego indeksowania
Z = [X, Y][N == "0"]
, ponieważ może to być interpretowane jako wartość logiczna rzutowana na indeks numeryczny.Nie golfowany:
źródło
Scala, 470 znaków
(
⇒
są standardowe scala, ale można je zastąpić,=>
jeśli liczymy bajty)Tutaj emulujemy cyfry na podstawie długości list, uważając, aby nie używać żadnych operacji numerycznych - tylko fałdy, mapy, zamki błyskawiczne i tym podobne. Liczba to lista tych cyfr (kolejność strategicznie odwrócona w połowie obliczeń); mnożymy poszczególne cyfry
flatMap
i nasze wiersze w góręreduce
.u
radzi sobie z wykrywaniem przeniesienia (przez bezpośrednie dopasowanie do listy> 10 elementów i rekurencją) i konwertowaniem cyfr z powrotem na znaki, a my używamy do tego,/:
aby przejść przez stos. Wymagany przykład kończy się w niecałą sekundę.źródło