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.


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.                                                    ";

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

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%}/

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

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


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())])

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.)


#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 ;-)


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ć:


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}))

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())

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.


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

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.


2

Perl: 38 40

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

Wydajność:

% perl code.pl
57 23 99 45
2101

25 78 63 15                                     
3174

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.


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();

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;
}
}

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

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!


Dlaczego zostało to zanegowane? Działa idealnie dobrze. (Przy okazji, eval('-'.join(x))sztuczka jest genialna.)
— trzęsienie ziemi

@flornquake Thanks!
— DLosc
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.