Złam kod do zamka szyfrowego

22

Biorąc pod uwagę standardowy zamek szyfrowy, taki jak na zdjęciu. Sposób odblokowania polega na wyrównaniu 4 cyfr w kodzie w wierszu kombinacji. Po latach lojalnej służby zostałeś zwolniony z fabryki zamków i zdecydowałeś się zemścić, nie zrywając zamków przed ich wysłaniem, pozostawiając w ten sposób każdy zamek z kombinacją, aby odblokować go na linii kombinacji.

Zamek szyfrowy

Wiesz również, że patrząc na kolejność liczb w innych liniach można ustalić, jakie liczby muszą znajdować się na linii kombinacji (a zatem i kombinacji, aby ją odblokować).

Jeśli każda linia na zamku otrzyma numer zaczynający się od linii 0 dla linii złożonej (linia, która odblokowuje zamek) do linii 9. Na przykład, jeśli liczby w linii 4 są 5336, to kombinacja do odblokowania będzie 1992.

Niestety zamki zostały już spakowane, a widok każdego zamka jest zasłonięty, więc możesz zobaczyć tylko liczby w różnych liniach zamka.

Wyzwanie

Biorąc pod uwagę 4 pary cyfr, gdzie pierwsza cyfra liczby całkowitej reprezentuje numer linii, a druga cyfra reprezentuje liczbę, która pojawia się w tej linii, opracuj kombinację do zamka. Na przykład jeśli wpiszesz:

57 23 99 45

Następnie powinien wypisać:

2101

Lub

25 78 63 15

i

3174

Załóżmy, że dane wejściowe będą zawsze 4 dodatnimi liczbami całkowitymi w postaci `25 64 72 18.

To jest , więc wygrywa najkrótszy program pod względem liczby bajtów.

Jest to również moje pierwsze pytanie, więc wszelkie uwagi są mile widziane.

Rory McPerlroy
źródło
Myślę, że musisz wyjaśnić dane wejściowe. Mówisz „ Biorąc pod uwagę 4 pary liczb całkowitych ”, a następnie podajesz przykład 57 23 99 45. To nie są cztery pary liczb całkowitych: to cztery liczby całkowite. I niektóre odpowiedzi zakładają, że otrzymają to jako ciąg, podczas gdy inne zakładają, że jest gotowy jako 4 ints.
Peter Taylor
Nie zgadzam się z tym, że cztery pary liczb całkowitych wyjaśniły format danych wejściowych, 57 to liczba całkowita 5 i 7, a nie liczba całkowita 57. Moje pierwsze założenie było takie, że linia miała 57, a kombinacja 23
Qwerty01
1
Co powiesz na „pary cyfr”? Byłoby to o wiele bardziej jasne i precyzyjne (a także działa z wiodącymi 0).
puszysty
Z technicznego punktu widzenia poprawnym terminem jest blokada permutacyjna . Większość „zamków szyfrowych” to w rzeczywistości zamki permutacyjne, ponieważ kolejność cyfr ma znaczenie.
nyuszika7h
Technicznie tak, jest to poprawne, ale nie sądzę, aby stanowiło chwytliwy tytuł.
Rory McPerlroy

Odpowiedzi:

32

CJam, 9 8 bajtów

ea9fbAf%

Czyta pary cyfr jako argumenty wiersza poleceń. Aby wypróbować kodu w Internecie , zmiany eado lS/odczytu z symulowanym stdin.

Przykładowy przebieg

$ cjam <(echo ea9fbAf%) 57 23 99 45; echo
2101
$ cjam <(echo ea9fbAf%) 25 78 63 15; echo
3174

Jak to działa

Kod znaku cyfry d to 48 + d . Zatem, biorąc pod uwagę dwucyfrowy ciąg xy, podstawowa liczba 9 daje 9 * (48 + x) + (48 + y) = 10 * (48 + x) + y - x ≡ y - x (mod 10) .

ea       " Push the array of command-line arguments.                                      ";
  9fb    " Mapped base 9 conversion; replace each string 'xy' with (9 * ord(x) + ord(y)). ";
     Af% " Take the results modulo 10.                                                    ";
Dennis
źródło
Cholera, nie możesz pozwolić nikomu wygrać, nie? : P
Optymalizator
Nie sądzę, że otrzymamy lepszą odpowiedź na CJam niż ta
Rory McPerlroy
1
Co się tam właśnie stało?
Wojna
1
@DigitalTrauma: Jasne, śmiało. Ciąg "99"jest interpretowany jako tablica [57 57]przez b; "xy"9bjest implementowany jako 9 * ord(x) + ord(y). Powinienem dodać to do mojej odpowiedzi.
Dennis
4
10 000 ledwo obejmuje wszystkie 2-znakowe programy, jeśli ograniczymy możliwe rozwiązania do ASCII drukowalnego.
Dennis
13

CJam, 13 12 11 znaków

Dzięki user23013 ma teraz do 11 znaków :)

4{Ar:--A%}*

Objaśnienia:

4{       }*     "Run the code block 4 times";
   r            "Read the next input token (whitespace separated)";
    :-          "Subtract 2nd number from the first treating r as a 2 numbered string";
  A   -         "Subtract the result of above from 10";
       A%       "Take modulus of 10 and store it on stack";

Wypróbuj online

Wiem, że można bardziej grać w golfa. Ale to moja pierwsza prawdziwa próba na CJam i jestem ograniczony doświadczeniem :)


Alternatywnie, inne metody, aby zrobić to samo z 1 dodatkową postacią:

l~]{_A/-A%}/     // My previous solution

lub

4{ri_A/-A%}*     // As pointed out by Ingo

lub

ea{i_A/-A%}/     // If input is passed through command line
Optymalizator
źródło
Czekałem na to. W przyszłym tygodniu ...
Soham Chowdhury
Pierwsze trzy postacie mogą być alternatywnie l~]. Wydaje mi się, że parsowanie danych wejściowych powinno być możliwe przy mniej niż trzech, ale nigdy wcześniej nie korzystałem z CJam: /
Ingo Bürk
4{ri_A/-A%}*jest o jeden bajt krótszy.
Ingo Bürk
1
Ach, lub co zrobiłeś z mojego wcześniejszego komentarza. Teraz są dwa 12-bajtowe rozwiązania! :)
Ingo Bürk
3
Lub 4{Ar:--A%}*.
jimmy23013
6

Golfscript (14 13 )

Wypróbuj online tutaj

Jest prawie taki sam jak rozwiązanie Optimizer , ale w innym języku. Trudno podejść do tego inaczej, ponieważ problem jest dość prosty , więc remis zdecydowanie trafia do Optymalizatora, którego wejście i tak było wcześniej.

~]{.10:^/-^%}/

Dla tej samej liczby bajtów możesz zrobić

~]{.10/- 10%}/
Ingo Bürk
źródło
Brak wstępnie zdefiniowanej zmiennej o wartości 10 w Golfscript?
Optymalizator
@Optimizer Niestety nie. Szkoda, ponieważ posiadanie danych wejściowych na stosie byłoby przewagą nad CJam.
Ingo Bürk
Tak, może to być 10 znaków w CJam (z wejściem na stosie) lub 11 w Golfscript (ze wstępnie zdefiniowaną zmienną)
Optimizer
Mógłbym też mieć 12 w Golfscript, gdybym tylko nie musiał zostawić miejsca - 10.
Ingo Bürk
1
heh, nawet najkrótsza języków mają swoje krótkie wchodzących: P
Optimizer
6

GNU dc , 14 bajtów

Pożyczka @ Sprytna sztuczka z bazą 9 Dennisa :

9i[?A%nd]dxxxx

Wprowadź liczby całkowite odczytane ze STDIN, po jednej w wierszu.

Wyjaśnienie:

9i                # Set input radix to 9
  [     ]         # push a macro, defined thus:
   ?              #   read number from STDIN and push
    A             #   push literal 10
     %            #   calculate number mod 10
      n           #   print, with no newline
       d          #   duplicate macro
         d        # duplicate macro
          xxxx    # execute the macro 4 times    

Wydajność:

$ for i in 57 23 99 45; do echo $i; done | dc ./combolock.dc
2101$ 
$ for i in 25 78 63 15; do echo $i; done | dc ./combolock.dc
3174$ 
$ 

Poprzednia odpowiedź, 18 bajtów:

Ponieważ myślałem, że mogę zbliżyć się do języków „golfowych” dzięki temu (ale nie zrobiłem tego):

[A?A~--A%n]dddxxxx
Cyfrowa trauma
źródło
1
Możesz zapisać bajt:9i[?A%nd]dxxxx
Dennis
@Dennis - Fantastycznie! Teraz jestem szyja z golfem i APL!
Digital Trauma
6

C 64 63 56 lub 61

Jeśli dane wejściowe można potokować z pliku

main(a){while(scanf("%d",&a)>0)putchar(48+(a-a/10)%10);}

Jeśli dane wejściowe należy wpisać jako standardowe

i;main(a){for(;i++-4;putchar(48+(a-a/10)%10))scanf("%d",&a);}

Odczytuje cztery liczby w pętli, a następnie przetwarza każdą z nich, odejmując pierwszą cyfrę od wartości i wypisując wynik modulo 10.

Oszczędności dzięki różnym komentarzom poniżej, a także zastosowaniu putchar zamiast printf

Alchymist
źródło
Fajne. Możesz zaoszczędzić przecinek, umieszczając scanfzewnętrzną stronę w for()ten sposóba,i;main(){for(;i++-4;printf("%d",(a-a/10)%10))scanf("%d",&a);}
Level River St
Możesz także zapisać 2 bajty, używając a*.9zamiasta-a/10
rev
@steveverrill Lubię to. Skoncentrowałem się więc na umieszczeniu wszystkiego w pętli for, czego mi brakowało
Alchymist
1
@AcidShout Przepraszamy - to nie działa. Na przykład 78 * .9 = 70,2, podczas gdy 78 - 78/10 = 71. Również użycie .9 promuje argument do podwojenia, więc nie mogę wziąć mod.
Alchymist
Możesz zaoszczędzić kilka bajtów, używając whilepętli i deklarując ajako argument main:main(a){while(scanf("%d",&a)>0)printf("%d",(a-a/10)%10);}
Dennis,
5

Python 3, 64

Bezpośredni.

print(''.join([(i-i//10)%10 for i in map(int,input().split())]))

Może być krótszy, jeśli mogę [2, 1, 0, 1]zamiast tego drukować, powiedzmy, ( 46 ):

print([i%10-i//10 for i in map(int,input().split())])
Soham Chowdhury
źródło
Możesz zaoszczędzić trochę, biorąc str((i-i//10)%10)bezpośrednio zamiast używać sekundy map(). Zacząłem od generatorów również dla moich, ale okazało się, że rzeczywista forpętla okazała się krótsza.
DLosc
Tak, dzięki za to!
Soham Chowdhury,
Dlaczego używasz list? Użyj genexps zaoszczędzić 2 znaki: print(''.join((i-i//10)%10for i in map(int,input().split()))). Także jeśli przestrzenie allowd na wyjściu można uniknąć joini wykorzystanie krotka-rozpakowaniu: print(*((i-i//10)%10for i in map(int,input().split()))).
Bakuriu
Chyba masz rację.
Soham Chowdhury,
4

C 92

#define a(n) ,(10+v[n][1]-*v[n])%10
main(int c,char**v){printf("%d%d%d%d"a(1)a(2)a(3)a(4));}

Dane wejściowe z wiersza polecenia. Odejmuje pierwszy kod ASCII każdego argumentu od drugiego, dodaje 10 i przyjmuje modulo 10.

Myślę, że po raz pierwszy napisałem printfz czterema %si bez przecinka (przecinek jest w #define.)

Level River St
źródło
#define f scanf("%c%c ",&a,&b);putchar(48+(9*a+b)%10)po którym następuje a,b;main(){f;f;f;f;}18 bajtów krótszych.
Dennis
@Dennis to świetna poprawa, ale zasadniczo jest to zupełnie inny program. Myślę, że jeśli ktoś to opublikuje, powinien to być Ty, a nie ja. Nie jestem pewien, czy miejsce w nim scanfjest konieczne, biorąc pod uwagę, że scanfma on analizować białe znaki tylko jako separator. Alchymist ma jeszcze lepszy pomysł w C. Ale wygląda na to, że już wygrałeś swoją odpowiedzią Cjam.
Level River St
Tak, zacząłem od zauważenia, że ​​spację a(n)można pominąć, potem zauważyłem, że wstawienie printf("%d%,...)makra pozwoliłoby zaoszczędzić kilka bajtów i w końcu trochę mnie poniosło ... - Miejsce jest potrzebne, ponieważ %cczyta się dowolną postać znak, więc przy drugim uruchomieniu zapisuje 32 w a. - Pokonanie CJam z C powinno okazać się trudne. printf()jest już tak długo, jak moja odpowiedź ...
Dennis
4

Java - 203 bajty

Tylko dlatego, że musi być wpis Java, widziałem dobrą okazję, aby dać szansę temu kodowi golfowemu (pierwsze zgłoszenie w historii).

class M{public static void main(String[] a){String r="";for(int i=0;i<4;i++){int l=Byte.valueOf(a[i].substring(1));int f=Byte.valueOf(a[i].substring(0,1));r+=(l-f<0)?l-f+10:l-f;}System.out.print(r);}}

Jeśli jest miejsce na ulepszenia, chętnie się o nich dowiem ;-)

Szlifierka
źródło
Możesz przeszukać [wskazówki] i uzyskać różne wskazówki dotyczące gry w golfa na początek :)
Optymalizator
Fajne dzięki! Sprawdzanie niektórych wskazówek pomogło mi zrzucić 13 bajtów :)
Sander
3

Lua - 46 znaków

while''do a,b=io.read(1,1,1)print((b-a)%10)end

Czyta trzy znaki na raz (daj mi małą litość wpisywania spacji na końcu), a mimo to a i b są ciągami-y ... ba MAGICZNIE pozwala im poczuć zdrową liczbę całkowitą dla dziecka. Czy zawijanie sprawdza się podczas drukowania.

Jak to uruchomić:

AndoDaan
źródło
1
Czy możesz podać przykładowe dane wejściowe / wyjściowe, wydaje się, że nie można go uruchomić na Ideone
Rory McPerlroy
@ Harry12345 Ach, przepraszam za to. Anarchy Golf zastanawia się, jak wdrożyć standard. Prawdopodobnie mógłbym to lepiej zakodować, ale mea, lua jest okropna. Podałem przykład mojego działania programu.
AndoDaan
3

JavaScript ES6 - 53 43 bajty

f=n=>n.replace(/.. ?/g,a=>(1+a[1]-a[0])%10)

Dość prosta funkcja, używa wyrażeń regularnych, aby uzyskać liczby. Wypróbuj na http://jsfiddle.net/efc93986/1/ . Jeśli funkcje nie są dozwolone, samodzielny program o 52 bajtach:

alert(prompt().replace(/.. ?/g,a=>(1+a[1]-a[0])%10))

Ponieważ ES6 działa obecnie tylko w przeglądarce Firefox, poniższy kod działa w każdej nowoczesnej przeglądarce o rozmiarze 70 bajtów:

alert(prompt().replace(/.. ?/g,function(a){return(1+a[1]-a[0])%10}))
NinjaBearMonkey
źródło
Kocham twoje 1+.
Neil
1
Pytanie mówi, aby zakładać prawidłowe dane wejściowe, więc możesz użyć ...?zamiast /\d+ ?. Spację po powrocie można pominąć. Ponadto, ponieważ nie określono konkretnego wejścia / wyjścia, powinieneś móc korzystać z funkcji.
Dennis
1
a-a[0]zamiast 1+a[1]-a[0]powinien również działać.
Dennis
2

Python 2 - 33 bajty

for i in input():print(i-i/10)%10

Akceptuje dane wejściowe użytkownika rozdzielane przecinkami. Np. Wejście:

29,26, 31, 88

Wydajność:

7
4
8
0

Jeśli dane wyjściowe są wymagane, aby dokładnie pasować do przykładu, jest znacznie dłuższy. 47 bajtów:

print"%d"*4%tuple((i-i/10)%10 for i in input())
feersum
źródło
input()nie działa w moim interpretatorze Python 2.
Soham Chowdhury,
@SohamChowdhury czy używałeś przecinków?
feersum
2
Nie, nie zrobiłem tego. Teraz działa. Na marginesie, myślę, że musisz wziąć dane rozdzielane spacjami zgodnie ze specyfikacją.
Soham Chowdhury,
3
Zgadzam się, dane wejściowe powinny być ograniczone przestrzennie
Rory McPerlroy
2

APL, 14

10|{--/⍎¨⍕⍵}¨⎕

Wyjaśnienie
pobiera dane z ekranu. Wartości rozdzielone spacjami są analizowane jako tablica.
{...}¨dla każdej liczby wprowadź ją do funkcji.
⍎¨⍕⍵bierze argument, utwórz tablicę jego cyfr.
--/oblicza jednostki minus dziesiątki.
10|mod 10.

TwiNight
źródło
1
Może to być 14 znaków, ale ma 24 bajty .
Ingo Bürk
ale do golfa kodowego zaliczamy się do UTF-8, a nie do jakiegoś specjalnego zestawu znaków. To byłaby tylko luka i może być łatwo wykorzystana.
Ingo Bürk,
1
@ IngoBürk Zgodnie z meta.codegolf.stackexchange.com/a/961/6972 odpowiedzi mogą być kodowane w dowolnym kodowaniu, chyba że OP stanowi inaczej. Rzeczywiście istnieje strona kodowa IBM dla znaków APL, która jest jednobajtowym odwzorowaniem, a dokładnie tego używał Dyalog przed Unicode 3.0. Jeśli nalegasz na Unicode, co jeśli wymyślę nowy język, który używa znaków innych niż Unicode? Jak byś na to policzył bajty?
TwiNight,
Mógłbym przysiąc, że domyślnie jest to UTF-8. Zatem 14 bajtów.
Ingo Bürk,
2

J - 20 15

Forma nie-czasownikowa (jako instrukcja zamiast definicji funkcji) jest krótsza o 5 znaków:

10|-~/|:10#.inv

Forma czasownika, która jest ładnym pociągiem :

10|[:-~/[:|:10#.inv]

Ten czasownik użyty na przykładowych danych wejściowych:

   10|-~/|:10#.inv 57 23 99 45
2 1 0 1
   10|-~/|:10#.inv 25 78 63 15
3 1 7 4

rotd =: 10|[:-~/[:|:10#.inv] NB. verb form

   rotd 25 78 63 15
3 1 7 4
   rotd 57 23 99 45
2 1 0 1
jpjacobs
źródło
2

Haskell 60 58

main=interact$show.map((\x->mod(x-x`div`10)10).read).words

Cyfry jednoznakowe, prawdziwy nemezis w grze w golfa w Haskell.

Zeta
źródło
2

Perl: 38 40

print abs($_-int$_/10)%10for split" ",<>

Wydajność:

% perl code.pl
57 23 99 45
2101

25 78 63 15                                     
3174
Riymus
źródło
1
1. Podkreślenia to składnia markdown, więc twój kod został trochę pomieszany. Aby temu zapobiec, wcięcie kodu z czterema spacjami. 2. absnie jest konieczne; x - x/10nie może być negatywne. 3. Jeśli używasz flag -040pe(zwykle liczonych jako 5 bajtów) do iteracji po danych wejściowych rozdzielanych spacjami, możesz skrócić swój kod do $_=($_-int$_/10)%10. 4. Jeśli wolisz unikać flag wiersza poleceń, nadal możesz zapisać kilka bajtów, ustawiając $/=$;i usuwając wywołanie do split.
Dennis
1

Rubin, 35 bajtów

$*.map{|n|a,b=n.bytes;$><<(b-a)%10}

Wyjaśnienie

Dane wejściowe są traktowane jako argumenty wiersza poleceń. String#byteszwraca tablicę liczb całkowitych (kody znaków ASCII). Ważna jest tylko różnica między kodem ostatniego i pierwszego znaku, a nie same liczby całkowite.

Britishtea
źródło
1

C # i LinqPad: 104

Util.ReadLine<string>("").Split(' ').Select(s =>(s[1]-s[0])).Aggregate("",(r,a)=>r+(a<0?10+a:a)).Dump();
EvilFonti
źródło
1

C ++ 118

int main()
{
int a,b,c;
for(int i=0; i<4; i++)
{
cin>>a;
b=a/10;
a=a%10;
c=a-b;
if(c<0)c+=10;
cout<<c;
}
}
Bacchusbeale
źródło
1. Nie jestem pewien co do innych kompilatorów, ale GCC wymaga #include<iostream>i std::przed cini cout. 2. Nie potrzebujesz warunkowego, jeśli pominiesz a=a%10. 3. Nie trzeba zmienne bi ctego, karetki i (z kilkoma modyfikacji) nawiasy wokół pętli.
Dennis
1
@SeanD: Proszę nie zatwierdzać zmian, które modyfikują kod. W tym konkretnym przypadku edycja unieważniła odpowiedź. Usunął również pierwszą linię, która powinna być obecna we wszystkich odpowiedziach.
Dennis
1
(CC @TeunPronk)
Dennis
@Dennis zwykle odpowiedzi na tej stronie nie zawierają wierszy preprocesora. #include<iostream>using namespace std;
Pominąłem
Wiem, że zwykle nie są one uwzględniane w liczbie bajtów, ale myślę, że powinny być obecne w odpowiedzi.
Dennis
1

PHP - 90 znaków

Pomyślałem, że wypróbuję kod golfa, więc oto moja pierwsza próba - prawdopodobnie można więcej.

<?php $a=array(57,23,99,45);foreach($a as$b){echo abs(substr($b,0,1)-substr($b,1,1)%10);}

58 znaków (dzięki uprzejmości Ismael Miguel)

for($i=0,$a=$_GET[n];$i<8;)echo abs($a[$i++]-$a[$i++]);

Uzyskaj dostęp do pliku za pomocą

file.php?n=57239945
Rory McPerlroy
źródło
Spróbuj tego kodu: <? for($i=0;$i<4;)echo abs($_GET[n][$i]%10);który ma 44 znaki. Dostęp z przeglądarki za pomocą file.php?n[]=xx&n[]=yy&n[]=xy&n[]=yx. (nieprzetestowany kod)
Ismael Miguel
Dobry pomysł, $_GETale wyświetla 57% 10 i potrzebuję (5-7)% 10
Rory McPerlroy
Spróbuj tego: <? for($i=0,$a=$_GET[n];$i<4;++$i)echo abs($a[$i][0]-$a[$i++][1]%10);. Niestety ma on 65 bajtów. (zapomniałem $iprzyrostu na ostatnim) Lub możesz spróbować <? for($i=0;$i<8;)echo abs($_GET[n][$i++]-$_GET[n][$i++]%10);uzyskać dostęp do przeglądarki, używając file.php?n[]=x&n[]=y&n[]=x&n[]=y&n[]=x&n[]=y&n[]=x&n[]=y61 bajtów długości.
Ismael Miguel
Tak, te drugie działają, trzeba to zrobić $_GET['n']. Zredagowałem moją odpowiedź.
Rory McPerlroy
Cóż, nie jest wymagane. Po prostu wydaje ostrzeżenie. To dobrze dla tej strony. Ale spróbuj tego: <? for($i=0,$a=$_GET[n];$i<8;)echo abs($a[$i++]-$a[$i++]);. %10Jest bezużyteczny, a to po prostu wygląda lepiej. Możesz również uzyskać do niego dostęp za pomocą file.php?n[]=xyxyxyxy. To rozwiązanie ma długość 58 bajtów.
Ismael Miguel
0

Python 3, 60

for x in input().split():print(-eval('-'.join(x))%10,end='')

Dane wejściowe i wyjściowe są dokładnie takie, jak określono, chociaż nie drukuje końcowego nowego wiersza. Dwie interesujące sztuczki tutaj: 1) zamiana dwóch wywołań na int()jedno wywołanie do eval(), i 2) używanie, join()aby uzyskać a-b, a następnie negowanie tego b-aw razie potrzeby. Na szczęście operator modulo Pythona podaje wartości dodatnie, nawet jeśli pierwszy argument jest ujemny!

DLosc
źródło
Dlaczego zostało to zanegowane? Działa idealnie dobrze. (Przy okazji, eval('-'.join(x))sztuczka jest genialna.)
trzęsienie ziemi
@flornquake Thanks!
DLosc