Na stronie Code Review natrafiłem na pytanie, które wydaje się interesujące. Myślę, że OP robi to źle, ale nie mogę być pewien ... Więc rozwiążmy to dla niego! (napisz program, a nie funkcję / procedurę)
Dane wejściowe (standardowe lub podobne):
Liczba całkowita x
w notacji dziesiętnej. Jest większy niż 1 i mniejszy niż 2 ^ 31.
Wyjście (standardowe lub podobne):
Liczba całkowita y
w notacji dziesiętnej. Produkt x * y
w postaci dziesiętnej musi zawierać tylko cyfry 0 i 1. Musi to być minimalna liczba większa niż 0.
Uwaga: wyjście nie jest ograniczone - jeśli minimum y
wynosi około 10 ^ 100, twój program musi wypisać wszystkie swoje 100 cyfr (nie wiem, czy istnieje rozsądny limit, na przykład 2 ^ 64, włączony) y
- nie rozwiązał go ).
Twój program powinien zakończyć się w rozsądnym czasie (1 sekunda? 1 godzina? - coś takiego) dla wszystkich x
w zasięgu.
Premia:
Jeśli twój program nie ma ograniczenia wielkości danych wejściowych (oprócz RAM) i ma złożoność wielomianową, pomnóż liczbę bajtów programu przez 0.8
i zaokrąglaj w dół.
Przykład: wejście 2
; wyjście 5
, ponieważ 2 * 5 = 10
Przykład: wejście 21
; wyjście 481
, ponieważ 21 * 481 = 10101
Oświadczenie: Nie jestem odpowiedzialny za pytanie w witrynie Code Review. W przypadku jakichkolwiek rozbieżności jedynie powyższy opis należy traktować jako właściwą specyfikację.
Odpowiedzi:
Pyth, 9 bajtów
Demonstracja
Dla każdej wielokrotności przekonwertuj na ciąg, odejmij cyfry w
10
(używając w tym przypadku przydatnej int Pyth'a do str stringu), a następnie logicznie zaneguj wynik, kończąc wyszukiwanie tylko wtedy, gdy zostanie znaleziona poprawna wielokrotność.Rozwiązanie premiowe, 10 bajtów:
To rozwiązanie faktycznie sprawdza, czy ciąg znaków reprezentujący liczbę może być traktowany jako liczba binarna (
i ... 2
) i kończy się, gdy błąd nie zostanie zgłoszony podczas tej próby.źródło
Python 2, wydajne rozwiązanie, 99
Dzięki Sp3000 za kilka wskazówek golfowych.
Wzywam wszystkich innych do opublikowania (we własnych odpowiedziach), ile czasu zajmuje uzyskanie wyniku do wprowadzenia
72
lub99
:) Jeśli są one naprawdę szybkie, spróbuj czegoś podobnego79992
(nadal <1 s tutaj).Wyjaśnienie:
Myślałem, że to nie jest konieczne (ponieważ kod jest dość czytelny), ale dostałem prośbę, więc oto:
Pierwszym pomysłem jest to, że liczba wyglądająca na binarną jest sumą 1 lub więcej różnych potęg równych 10. Dlatego możemy próbować dodawać różne potęgi 10 na różne sposoby, aż otrzymamy resztę 0.
Jeśli robimy to naiwnie, to to samo, co generowanie wszystkich liczb binarnych i testowanie ich. Ale wiele resztek pozostanie takich samych. Lepszym sposobem jest zapisanie tylko najmniejszej liczby, która dała pewną pozostałą część, i sukcesywne dodawanie większych mocy 10 do liczb, które zanotowaliśmy. Tak właśnie działa program.
d
jest słownikiem / mapą, w której klucze są resztkami, a wartości są liczbami binarnymi z resztą. Inicjałn:0
jest szczególnym przypadkiem: ma to być0:0
, abyśmy mogli zacząć dodawać do niego moce, ale algorytm zatrzymuje się po znalezieniu klucza 0, więc użyłemn
zamiast tego, co gwarantuje, że będzie miało ten sam efekt i nie będzie kolidować z innymi wartościami.Następnie zaczynamy dodawać moce 10 (zapisane w
k
) do wszystkich istniejących liczb i rejestrować pozostałe. Dodajemyk
do reszty:(x+k)%n
i do liczby:d[x]+k
i zapisujemy ją tylko wtedy, gdy jest to nowa reszta:,d.setdefault(…)
następnie przejdź do następnej potęgi:k*=10
i powtarzaj, aż otrzymamy klucz 0:while min(d)
Na koniec
d[0]
podaje binarnie wyglądającą liczbę, która pozostała 0 modn
, więc dzielimy ją,n
aby uzyskać rozwiązanie.Uwaga: program można usprawnić, unikając dużych liczb (rejestrowanie wykładników zamiast potęg 10 i obliczanie reszt potęg z poprzednich wartości), ale to kod golfowy, więc ...
W rzeczywistości tutaj napisałem szybszą wersję:
źródło
Python 2, 47 bajtów
Śledzi numer wejściowy
n
i bieżącą wielokrotnośća
. Kiedya
wygląda jak binarny, wypisz stosuneka/n
. Aby sprawdzić, czy liczba składa się z0
„i1
”, porównujemy maksymalny znak w reprezentacji ciągu z'1'
.Używa
str(a)
zamiast`a`
unikać długich zakończeńL
. Niestety'L'
jest większy niż'1'
.źródło
Perl, 27 bajtów
Licząc shebang jako jeden, dane wejściowe są pobierane ze standardowego wejścia.
Przykładowe użycie
Perl, 25 bajtów
Poprawę dwa bajt przez @skmrx .
Zamiast sprawdzać pod kątem wyrażenia regularnego, próbuje to ocenić produkt jako literał binarny. Po awarii przechodzi do następnego. Zazwyczaj
oct
funkcja ta byłaby używana do tego celu, ale po cichu przycina nieprawidłowe cyfry, co nie jest przydatne w tym wyzwaniu.Perl, 40 bajtów
O wiele bardziej wydajne rozwiązanie. Iterujemy reprezentacje binarne, interpretujemy je jako podstawę 10, a następnie sprawdzamy podzielność. Czas działania dla wszystkich wartości poniżej 100 jest nieistotny.
Przykładowe użycie
źródło
eval"0b".$_*++$\||redo}{
use bigint
aby obsługiwać duże liczby, które OP upoważnia do obsługi :(oct'0b'.++$\*$_
, ale po cichu przycina nieprawidłowe cyfry.eval
Zamiast tego nie pomyślałem o użyciu .JavaScript, 43 bajty
To skończyło się znacznie krócej, niż myślałem. Zasadniczo zwiększa
y
się o 1 doy * (input number) = (binary-looking number)
. Oczywiście dość nieefektywne.JavaScript (bardziej wydajne rozwiązanie), 53 bajty
Ten zwiększa się
y
w postaci binarnej doy / (input number) = (number without a remainder)
. Potem wyprowadza(number without a remainder)
.JavaScript (jeszcze bardziej wydajne rozwiązanie), 76 bajtów
Ten łączy obie poprzednie metody opisane powyżej. Sprawdza przyrosty
y
do momentu, aż alboy * (input number) = (binary-looking number)
(co oznacza, że dane wyjściowe sąy
) LUBy / (input number) = (number without a remainder)
(co oznacza, że dane wyjściowe są(number without a remainder)
).źródło
Haskell,
7270646058 bajtówEdycja: @Jan Dvorak pomógł mi zaoszczędzić 4 bajty.
Edycja: @BlackCap zapisał 2 bajty, przechodząc do
do
notacji. Dzięki!źródło
main=print.f=<<readLn
main=readLn>>= \x->print$[y|y<-[1..],all(<'2')$show$x*y]!!0
main=do x<-readLn;print$[y|y<-[1..],all(<'2')$show$x*y]!!0
Python 2,
67656360 bajtówDzięki Status za 2 bajty i Shebang na 5 bajtów!
źródło
b=1
any(c in`a*b`for c in'23456789')
not c in`a*b`for c in'10'
zadziała?set('a*b')&set('23456789')
.`
produkujeL
na długo i'L'>'1'
.JavaScript (ES6) 222
250Korzystanie z matematyki o dowolnej precyzji (operowanie na ciągach cyfr dziesiętnych)
Można to trochę pograć w golfa(gotowe), ale podoba mi się to, że nie ogranicza się to do standardowych liczb JS (17 cyfr dziesiętnych precyzji) i jest szybki.Przetestuj poniższy fragment kodu w przeglądarce zgodnej z EcmaScript 6. Czas jest dopuszczalny do 9998 - nie próbuj 9999 i bądź cierpliwy z 999.
Bardziej czytelny
Jest to pierwsza wersja z modułem i długim podziałem jako oddzielnymi funkcjami.
źródło
Perl, 45 bajtów
źródło
Pyth, 10 bajtów
Uruchom kod.
Port mojego Pythona odpowiedź , biorąc od Maltysen zastosowanie
f
do znalezienia pierwszego dodatnią liczbę, która spełnia warunek.źródło
PHP, 50 bajtów
Niektóre przypadki testowe
źródło
CJam,
191716 bajtówWypróbuj online
Rozwiązanie z użyciem siły brutalnej, próbując wartości kolejno, aż do znalezienia jednego spełniającego warunek.
Najnowsza wersja oszczędza 2 bajty dzięki użyciu
As
zamiast"01"
budowania łańcucha zawierającego0
i1
, jak sugeruje @aditsu. Całkowicie zaproponowane rozwiązanie w komentarzu oszczędza kolejny bajt, ale wygląda całkiem inaczej niż mój, więc nie chciałem umieszczać go pod własnym nazwiskiem.I jeszcze 1 bajt zapisany przez @Dennis.
Wyjaśnienie:
źródło
li0{1$+_sAs-}g\/
As
zbudować ciąg, ponieważ jest to bardzo lokalne zmiany, które z perspektywy czasu (który jest zawsze o wiele łatwiejsze ...) Powinienem myśli.li:V!{)_V*sAs-}g
Również0{)_easi*sAs-}g
(15 bajtów) współpracuje z interpretera wiersza polecenia i argumenty Javy.Python
32,10176 bajtów-25 bajtów dzięki @aditsu
prawie tak wydajne jak rozwiązanie @ aditsu
Zamiast próbować przechodzić między mnożnikami w porządku rosnącym, próbuję zapętlać produkty, które generuję w formie „binarnej”.
źródło
n=input()
),while b%n:
(zainicjujb
na 1), bez wcięćbin(m)[2:]
powinien być krótszy niż ciąg formatu. Włączone podwójne przypisanie równieżb=m=1
powinno zaoszczędzić kilka.Java, 213 bajtów
Wykorzystuje
BigInteger
s i jako taki ma (dla wszystkich uzasadnionych intencji i celów) nieograniczony rozmiar danych wejściowych. Nie jestem jednak pewien, czy złożoność zależy od tempa wzrostu naszej funkcji tutaj.Dzięki geobitom i ypnypn za oszczędność garści bajtów.
źródło
static
modyfikator do metody.b.ONE
i!(b.multiply(c)+"")
(zamiasttoString()
).C, 3675 bajtów
Tak długo na Code Golf ...
Uruchomić bez parametrów wiersza poleceń - to dostaje
n
odstdin
i wysyła wynikstdout
. Uruchom z nazwą pliku - zapisuje wyniki dlan = 1...10000
tego pliku i mierzy czas.Wydajność dla 1 ... 10000: 140 ms
Ten kod wykorzystuje algorytm zaproponowany przez aditsu , zaimplementowany w C dla prędkości. Nie próbowałem go golfa, więc kod będzie łatwiejszy do odczytania.
Najpierw zaimplementowałem go w C ++,
std::map
rejestrując wyniki wyszukiwania, i było to dość powolne. Jednak kluczemap
są kolejnymi liczbami całkowitymi (nazywam jemod
s, ponieważ reprezentują liczby modulon
), więc naturalne jest użycie tablicy - więc przepisałem ją w C.Dodatkowa optymalizacja dotyczy wartości mapowania - aby uniknąć zapisania dużej liczby całkowitej dla każdej
mod
, przechowuję tam tylko największą potęgę 10 - wystarczy tyle informacji, aby przejść do poprzedniegomod
. Tak więc tablica jest naprawdę drzewem / wykresem wyszukiwania. Kiedy wyszukiwanie dotrze domod = 0
, śledzenie węzłów drzewa z powrotem do katalogu głównego daje moc 10 w kolejności malejącej.Ponieważ wyszukiwanie zwykle zatrzymuje się dość szybko, a odwiedzana jest tylko niewielka część węzłów, potrzebuję listy aktywnych węzłów. Jest zaimplementowany jako tablica
mod_list
o długościmod_list_length
.Niektóre statystyki środowiska wykonawczego (na komputerze z 16 GB pamięci RAM, co wydaje się być ważne dla dużych
n
, ponieważ program przydziela5n
bajty pamięci):99999999
- 2 sekundy999999999
- 27 sekund (wynikiem jest111111111222222222333333333444444444555555555666666666777777777888888889
- prawdopodobnie największy możliwy wynik dla 32-bitowych liczb całkowitych)2147483647
- 26 sekund (wynik jest4661316525084584315813
)1999999998
- 52 sekundy (prawdopodobnie najdłuższy możliwy czas działania dla 32-bitowych liczb całkowitych)źródło
C ++ 11, wiele bajtów, bardzo szybko, wow (1,5 s dla 1999999998, 0,2 s dla 1… 10000)
(Gra w golfa w wersji Python poniżej.)
Zaczynamy od koncepcji nieco podobnej do rozwiązania aditsu, w której indukcyjnie budujemy kolekcję modułowych resztek, które są osiągalne w n krokach. Ale zamiast czekać, aż znajdziemy resztę 0, sprawdzamy dwie znalezione resztki aib tak, że a · 10 ^ n + b = 0. To podejście w środku spotkania zmniejsza o połowę głębokość drzewa wyszukiwania, więc jest to znacznie szybciej na dużych wejściach i zużywa znacznie mniej pamięci.
Niektóre punkty odniesienia:
Kod:
Python, 280 bajtów (8,6 sekundy w 1999999998 z PyPy)
źródło
Matematyka 115 bajtów
źródło
Java 156 bajtów
Ogromne podziękowania dla aditsu :)
źródło
[]
,y
może byćlong
też, zapomniałeśx*y+""
sztuczki w 2. programie, użyjisEmpty
zamiast sprawdzania długości, użyj;
zamiast{}
long
tego nielong x=…,y;
y
musi zaczynać się od 1, możesz zainicjować ją w deklaracji, twoja klasa nie musi być publiczna i możesz przejśćy++
dox*y
part (x*y++
)Pyth -
1211 bajtówUżywa filtra z argumentem numerycznym, aby uzyskać pierwszą liczbę naturalną, która spełnia predykat, domyślnie jest to 1, czego chcemy. Ustaw inaczej, aby sprawdzić, czy tylko zera i jedynki.
Pakiet testowy .
źródło
"01
. Oszczędza jeden znak.R, 45 bajtów
Stosowanie:
źródło
Java,
198193181 bajtówDzięki @aditsu za zgolenie 5 bajtów ORAZ zwiększenie zakresu liczb testowalnych!
Zauważ, że niektóre wartości zapętlają się ujemnie z powodu tego, jak Java analizuje liczby całkowite. Można to obejść przez BigInteger, ale premia była po prostu mniej cenna.
Wiem, że nie zamierzam wygrywać, ale mam nadzieję, że inspiruje to inne, krótsze odpowiedzi.
Niegofolowany:
źródło
Long
jest krótsze niżInteger
:)C,
107101 bajtów (10599 bajtów dla 32 bitów)Istnieje wyraźny brak odpowiedzi w C na temat golfa kodowego. Rzeczywiście, C nie jest najlepszym wyborem do pisania najmniejszego możliwego programu, ale nie jest tak źle:
Możesz obejść się bez #include, ale wtedy wszystkie definicje funkcji będą niejawne. Główną wadą jest to, że powoduje to założenie, że wszystkie funkcje zwracają wartości int. Jest to problem na maszynach 64-bitowych dla funkcji, które faktycznie zwracają wskaźnik. Jeśli korzystasz z komputera 32-bitowego, powyższe rozwiązanie można ogolić 2 bajty:
Nieco bardziej czytelna wersja:
źródło
Czas C # w pobliżu 5 sekund (od 1 do 10000)
Zgodnie z życzeniem, oto program C # w golfa odpowiadający na oryginalne wyzwanie. Wprowadź jako argument wiersza poleceń, wyślij do konsoli.
Jeśli chodzi o nagrodę: nagrodę należy przejść do aditsu, ponieważ uważam, że jego algorytmu nie da się pokonać pod względem wydajności. Ale anatoligia samo odpowiedź jest również niesamowita.
Oto moja szybka implementacja w C #. Podejrzewam, że w C ++ może być szybszy (może 2x). Skompilowane i przetestowane z Visual Studio 2010, .NET Framework 4, 64 bity, przekierowując dane wyjściowe do nul. Czas: 00: 00: 05.2604315
źródło
Keys.Reverse
? Czy kolejność jest ważna? Jeśli to tylko w celu uniknięcia problemów z współbieżnością,ToList
jest krótsze.C z GMP (621 bajtów, szybki)
Starałem się być szybki i niski, ale szybko faworyzowałem. Ta implementacja wykorzystuje nieco ulepszoną wersję teoretycznego przyspieszenia, o którym wspomniałem w komentarzu do odpowiedzi aditsu .
Zapisz jako
pseudobinary.c
i kompiluj zgcc pseudobinary.c -lgmp -o pseudobinary
. Zauważ, że przydziela to tyle pamięci dla dużych danych wejściowych, że będziesz musiał ją skompilować dla platformy 64-bitowej.Wersja pętli dla taktowania (751 bajtów)
Wersja bez golfa
źródło
C + GMP, 669
Jest to bardzo szybkie w przypadku małych liczb; zaczyna dusić się, gdy wynik ma więcej niż 64 cyfry.
Wersja z zapętleniem do 10000 (671 bajtów):
Oto kilka poleceń do testowania mojego kodu, a także moich konkurentów i wyników na moim laptopie:
źródło
T-SQL,
164156155154159 bajtów(-1 bajt. Dzięki Jonathan!)
(-1 więcej, bo dlaczego mam spacje końcowe na liniach? SMH)
(+5 zdałem sobie sprawę, że moje golfa zepsuły się)
Nie wiem, dlaczego ciągle wracam do tych pytań, w których powinienem przekonwertować na Binary ... T-SQL nie wie, jak to zrobić poprawnie.
W każdym razie oto SQLFiddle .
Bez golfa:
O ile mi wiadomo, większość tych rzeczy jest wymagana do napisania funkcji w języku T-SQL.
Utwórz pusty ciąg, który będziemy przechowywać jako nasz numer binarny.
Zapisz wartość wejściową do wykorzystania na końcu. Wydaje się, że powinien istnieć sposób na użycie oryginalnego wejścia, nawet jeśli zmienimy wartość, ale nie mogę jej znaleźć.
Więc bierzemy nasze oryginalne wejście, MOD to z 2, aby znaleźć resztę, a to będzie nasza następna najmniejsza cyfra. Na przykład 5% 2 = 1
Następnie bierzemy nasz numer i dzielimy go na pół. Ponieważ jest to
int
typ, zaokrągla go w dół do najbliższej liczby całkowitej, więc 5/2 = 2. KONIEC Następnie przechodzimy przez to, aż wartość wynosi 0. Tak więc otrzymujemy 5% 2 = 1 5/2 = 2 2 % 2 = 0 2/2 = 1 1% 2 = 1 1/2 = 0, co daje nam wartość ciągu binarnego 101.Bierzemy nasz ciąg binarny i ponownie konwertujemy go na inny
int
.Zwracamy ciąg binarny
int
podzielony przez naszą pierwotną wartość, według źródła pytania.źródło
@>0 SELECT
nie da się pominąć?Rubinowy, 46 bajtów
Naprawdę powinienem wyeliminować pętlę while za pomocą alternatywnej pętli.
Edycja: Dzięki @manatwork za zgolenie 1 bajta!
Edit2: Dzięki @histocraft za szalone 9 bajtów!
Edycja: Jeszcze raz dziękuję @manatwork za golenie 7 bajtów!
źródło
z!=z[/[01]+/]
jest krótszy.z[/[^01]/]
jest jeszcze krótszy.z="#{n.to_i*k+=1}"while z[/[^01]/]
Scala, 114 bajtów
Wersja do odczytu
źródło
brutalna siła gawk4, 28 + 2 = 30 bajtów
Musi zostać wywołany za pomocą
-M
opcją używania dużych liczb. Oczywiście jest to absurdalnie wolne, użycie dużych liczb spowalnia go jeszcze bardziej, ale teoretycznie wejście nie jest ograniczone, a użycie pamięci RAM jest znikome.Przykład użycia (jeśli masz czas do stracenia
;)
)Zoptymalizowany gawk4, 69 + 2 = 71 bajtów
Cóż, ostatecznie okazało się, że jest to klon odpowiedzi aditsu. Po spojrzeniu na to pytanie wciąż zastanawiałem się, jak zakodować część sumy częściowej, kiedy nie mogłem się oprzeć spojrzeniu na inne odpowiedzi tutaj.
W tablicy awk elementy mają takie (dziwne?) Zachowanie, że jeśli porównasz nieistniejący element z czymś, zostanie on w jakiś sposób zainicjowany jako pusty przed porównaniem (przyznam, że nie jestem całkiem pewien, co się tam dzieje). Więc po sprawdzeniu
!a[0]
przezfor(i in a)
starty pętli nawet bez inicjowaniaa[$0]
aby0
jak aditsu zrobił.Oczywiście w tym
-M
celu należy również skorzystać z opcji.Chociaż jest dość szybki, wciąż jest znacznie wolniejszy niż Python. Do
79992
tego zajmuje około 14 sekund na moim Core2Duo 2GHz. I nie powiedziałbym, że działa dla danych wejściowych do 2 ^ 31, ponieważ w najgorszym przypadku musi zbudować tablicę dużych liczb (gawk4 używa do tego GMP), która ma wielkość liczby wejściowej. Jako „bonus” duże tablice są bardzo wolne w awk ...źródło
Dyalog APL , 25
Definiuje to odpowiedni program „P” (nie tylko funkcję bez nazwy):
2∘
zacznij od 2 jako lewy argument,0::
jeśli wystąpi błąd ...⍵∇⍨1+⍺
wywołaj się z przyrostowym lewym argumentem⍺×⍵
pomnóż lewy i prawy argument⍕
przekształć w łańcuch,⍎¨
aby każdy znak stał się~
logiczną próbą NIE (jeśli się nie powiedzie, przejdź do obsługi błędów powyżej, w przeciwnym razie ...)⍺⊣
zwraca bieżący lewy argument.źródło