Zwykły N-cyfrowy zamek szyfrowy składa się z N obracających się tarcz. Każda płyta ma kolejno wpisane cyfry 0–9, a aby ją otworzyć, należy ustawić odpowiednie hasło. Oczywiście, jeśli nie znasz hasła, musisz spróbować najwyżej 10 N razy przed jego odblokowaniem. To nie jest interesujące.
Rozważmy więc wariant zamka szyfrowego, nazwijmy go zamkiem ujawniającym odległość.
Przy każdej nieudanej próbie otwarcia zamka ujawniającego odległość reaguje na minimalną liczbę ruchów do odblokowania.
Jeden ruch jest definiowany jako obrót o jedną pozycję, na przykład wymaga 1 ruchu od 890
do 899
i 9 ruchów od 137
do952
.
Wyzwanie
Biorąc pod uwagę zamek ujawniający odległość z nieznanym hasłem, spróbuj otworzyć zamek przy minimalnej liczbie prób (nie ruchów), jednocześnie zapobiegając zbyt długiemu programowi.
Zasady i wyniki
- Powinieneś napisać pełny program, który wprowadza dane ze stdin i wypisuje na stdout. Program powinien wykonać wejście / wyjście w następujący sposób:
Start
Input an integer N (number of digits) from stdin
Do
Output a line containing decimal string of length N (your attempt) to stdout
Input an integer K (response of the lock) from stdin
While K not equal 0
End
Twój program powinien obsłużyć do N = 200 i powinien działać mniej niż 5 sekund na dowolnym wejściu.
Zera wiodące w danych wyjściowych nie powinny być pomijane.
Jest 5 danych testowych dla każdej długości, więc całkowita liczba danych testowych wynosi 1000. Dane testowe są generowane losowo.
Ostateczny wynik to (całkowita liczba domysłów we wszystkich danych testowych) * ln (długość kodu w bajtach + 50). Najniższy wynik wygrywa. (ln jest logiem naturalnym)
Zdobędę dla ciebie program. Jeśli chcesz wiedzieć, jak zdobędę punkty w twoim programie lub chcesz go zdobyć samodzielnie, spójrz na poprzednie zmiany w tym poście .
To wyzwanie zakończy się o godzinie 2017.12.12 14:00 UTC. Wyślę wtedy moje rozwiązanie.
Przykład biegania
Linie zaczynające się od >
reprezentują dane wejściowe, a inne reprezentują dane wyjściowe programu.
Możesz mieć hasło w pamięci i wchodzić w interakcje z programem, aby je przetestować.
> 3 # 3-digit lock. The hidden password is 746
000 # 1st guess (by program)
> 11 # response to the 1st guess
555 # 2nd guess
> 4 # ...
755
> 2
735
> 2
744
> 2
746 # finally the correct answer! The program attempts 6 times.
> 0 # this is not necessary
Przykładowy program
EDYCJA: Być może powyższy format wejścia / wyjścia nie był jasny. Oto przykładowy program w Pythonie.
Python, 369 bajtów, łączna liczba prób = 1005973, wynik = 6073935
import sys
N = int(input()) # get the lock size
ans = ''
for i in range(N): # for each digit
lst = []
for j in range(10): # try all numbers
print('0' * i + str(j) + '0' * (N - i - 1)) # make a guess
result = int(input()) # receive the response
lst.append(result)
ans += str(lst.index(min(lst)))
print(ans) # output the final answer
Dzięki Jonaszowi za uproszczenie wyzwania.
źródło
162751*ln(388+50)=989887
.C # (.NET Core) , 617 bajtów, łączna liczba prób = 182255, wynik = 1185166
Mam nadzieję, że C # w tym formacie działa dla Ciebie. Ma postać kompletnego programu, więc powinien istnieć sposób na kompilację do pliku wykonywalnego. Daj mi znać, jeśli mogę coś zrobić, aby to ułatwić. Bajty są częścią punktacji, mimo że tag Code Golf został usunięty, więc moje oficjalne zgłoszenie usuwa wszystkie niepotrzebne białe znaki i przydatne nazwy. Moje wyjaśnienie poniżej użyje fragmentów niepoznanego kodu:
Wyjaśnienie
Ten program używa tylko jednej metody pomocniczej:
Spowoduje to zapisanie domysły na stdout, a następnie odczyta odległość od stdin. Również natychmiast kończy program, jeśli zgadnięcie jest dokładną kombinacją. Często to nazywam. Następnie wstępna konfiguracja:
Pobiera długość kombinacji, a następnie rozpoczyna zgadywanie ze wszystkimi zerami. Następnie iteruje każdą cyfrę w
for
pętli.Dla każdej cyfry zgaduje 5, a następnie decyduje o kolejnym kroku na podstawie zmiany odległości od poprzedniej domysły (gdzie ta cyfra wynosiła 0).
Jeśli odległość wzrosła o 5, wówczas 0 było prawidłowe dla tej odległości. Dostosuj tę cyfrę z powrotem do 0. Ręczna zmiana zarejestrowanej odległości zapobiega dodatkowemu zgadywaniu.
Jeśli odległość zmniejszyła się o 5, wówczas 5 jest poprawną cyfrą i natychmiast przechodzimy do następnej cyfry.
Po tym wszystko jest trudne. Użycie
5
i0
dla moich początkowych domysłów oznacza, że pozostałe możliwości różnic są3, 1, -1, -3
z 2 możliwościami dla każdej, które wymagają 1 dodatkowego odgadnięcia, aby rozróżnić. Każdy z tych przypadków ma podobną formęNiektóre liczby się zmieniają, ale zasadniczo wypróbowujemy jedną z dwóch możliwości i sprawdzamy, czy zmiana była poprawna dla tej cyfry. Jeśli tak nie było, to druga cyfra jest poprawna, więc ustawiamy tę cyfrę, a następnie dostosowujemy różnicę ręcznie.
Ta metoda oznacza, że powinniśmy wymagać maksymalnie 1 zgadywania dla początkowych zer, 2 zgadnięć na cyfrę, a następnie 1 zgadywania końcowego, aby upewnić się, że ostatnia cyfra nie spadnie.
Może to być wadliwe, działa, o ile sprawdziłem ręcznie, ale to nie jest gwarancja.Błąd znaleziony i zgnieciony dzięki Colera Suźródło
37
. Wyjście to:00, 50, 30, 75, 75
(tak, dwa 75s).<
z>
każdymif
INswitch
wydaje się usunąć błędu. Jeśli tego właśnie chcesz, Twój wynik to182255*ln(617+50)=1185166
.Python 2 i 3: 175 bajtów, łączna liczba prób = 1005972, wynik = 5448445
Ten program wymaga pułapu (log (n)) * 10 prób na kombinację lub każda cyfra wymaga 10 prób (czyli
333
30 prób).Ogromne podziękowania dla Colera Su za pomoc w zakresie funkcji wejścia / wyjścia.
Wersja Python Challenge ( zmodyfikowana przez OP ).
Napisałem wersję kodu blokady w Pythonie. Możesz przejść dalej i użyć, jeśli próbujesz rozwiązać ten problem w Pythonie (tak jak ja). Poniższe działa w Pythonie 2 i 3. Bardziej sensownym było zaimplementowanie blokady jako klasy, na której można testować, i postanowiłem stworzyć funkcję generatora do odgadywania danych wejściowych.
źródło
LockIO
źle napisałem klasę. Wysłałem prośbę o edycję. Po drugie, myślę, że źle odczytałeś kryterium punktacji. Wynik jest obliczany na podstawie danych testowych wygenerowanych przez generator, a nie przykład (wykonałem twój program, a całkowita liczba to 1005972). Brakuje również dziennika naturalnego. Po trzecie, określiłem, że musisz dostarczyć pełny program, więc powinieneś również uwzględnić tęLockIO
część w liczbie bajtów. Dodatkowo musisz podać wynik końcowy, który również jest liczony w wyniku.Lock
imasterLock
jest dla wygody testowania.LockIO
jest tym, co faktycznie musisz przesłać, ponieważ używa wymaganego formatu We / Wy.R ,
277 bajtów (wynik = 1175356)258 bajtów, łączna liczba prób = 202999, wynik = 1163205Wypróbuj online!
Wersja stdin-stdout, zgodnie z żądaniem OP, bez płyt grzewczych. Dzięki Colera Su za naprawienie początkowego błędu. To jest nieco krótsza wersja niż ta w komentarzach.
Poniżej przedłożenie TIO w celu przeprowadzenia serii testów w TIO
R 189 bajtów
Wypróbuj online!
Rozważmy wektor zer jako wstępne zgadywanie. Nazwijmy V odległość między bieżącą zgadywanką a rozwiązaniem. Dla każdej pozycji musisz tylko sprawdzić zmiany w V, gdy zamienisz 0 na 5 i na 4. W rzeczywistości różnice między zmianą 0 na 5 są wymienione w moim wektorze s1. Różnice między zmianą 0 na 4 są wymienione w moim wektorze s2. Jak widać, te dwa wektory jednoznacznie odwzorowują cyfry rozwiązania.
Łączna liczba testów wynosi zatem
3 * L2 * L + 1, gdzie L jest długością kodu: wstępne sprawdzenie wszystkich zer, następnie dwa sprawdzenia każdej cyfry, jeden przeciwko 5 i jeden przeciwko 4.Ulepszenie z czynnika 3 do czynnika 2 zostało zainspirowane poddaniem się Kamila Drakariego.
Reszta przedłożenia TIO jest płytą kotłową dla R. Przedłożenie TIO pokazuje czas działania i całkowitą liczbę operacji dla 1000 przebiegów z L = 1 ... 200, 5 powtórzeń dla każdej wartości L.
źródło
Error in scan(n = 1) : scan() expected 'a real', got 'S=rep(0,L)'
podczas wykonywania.scan(file=file("stdin"),n=1)
działa. Ten program (taki sam jak twój, właśnie poprawiony I / O) uzyskał wynik202999*ln(277+50)=1175356
.202999*ln(258+50) != 202999*ln(277+50)