Poliziotti e ladri: primatologia redatta (filo dei ladri)


9

Questo è il filo dei ladri. Il thread della polizia è qui .

La tua sfida è quella di prendere una presentazione non crackata dal thread della polizia e provare a trovare il programma originale non modificato. Si prega di commentare l'invio del poliziotto dopo aver decifrato il loro codice.

Risposte:


6

brainfuck , Jo King

>>>>>+>,[>++++++[-<-------->]<+>,]<[-[█<█<]++++++++++<]>[-]>>██[>█>>█>]+[<]<<[<]>█<<+>>[>]█>[>]█+[<]<<[<]>-█>]>>[->]<[-[[<]<]++++++++++<]>[-]>[<█]>]>[>]<[[█]<]<<<<<[<]<<██>>[>]<█[->+<]<█>>[>]<[-[[<]<]++++++++++<]>███>[<<]>[[[>]>████[<]<[-[[<]<]++++++++++<]>[-]>[█<]>]>[>]<[[-]>+[>]<-<[<]<]+<<<<<[<]>[[>]+[[>]>]>[>]>[-<+>]<[<]<[>+[<]>>-<<<<<[[<]<]>>███████>[[█]>]<]<[[<]<]<[█]>]>>>[[>]<->>]]>[[>]>]<<[[[█]<]<]<<<[█]<<█>>>[>]█[-[[<]<]++++++++++<]>>[[>]+[------->++<]>.+.+++++.[---->+<]>+++.>>]>[>]+[------->++<]>++.++.---------.++++.--------.
>>>>>+>,[>++++++[-<-------->]<+>,]<[-[[<]<]++++++++++<]>[-]>>[[[>]>>[>]+[<]<<[<]>[<<+>>[>]>>[>]<+[<]<<[<]>-]>]>>[->]<[-[[<]<]++++++++++<]>[-]>[<<]>]>[>]<[[-]<]<<<<<[<]<<[>>>[>]<[[->+<]<]>>[>]<[-[[<]<]++++++++++<]>[-]>[<<]>[[[>]>[>]+[<]<[-[[<]<]++++++++++<]>[-]>[<<]>]>[>]<[[-]>+[>]<-<[<]<]+<<<<<[<]>[[>]+[[>]>]>[>]>[-<+>]<[<]<[>+[<]>>-<<<<<[[<]<]>>[[-]+>]>[[>]>]<]<[[<]<]<[<]>]>>>[[>]<->>]]>[[>]>]<<[[[-]<]<]<<<[<]<<]>>>[>]<[-[[<]<]++++++++++<]>>[[>]+[------->++<]>.+.+++++.[---->+<]>+++.>>]>[>]+[------->++<]>++.++.---------.++++.--------.

Provalo online!

Questo implementa il setaccio di Eratostene.

L'iniziale >>>>>+>,[>++++++[-<-------->]<+>,]inserisce ciascuna cifra come un codice carattere e sottrae 47 per metterlo nell'intervallo 1-10. Ciò consente a un valore di cella 0 di indicare la spaziatura tra i numeri. L' +>inizio vicino di questa sezione impone che il numero sia di almeno due cifre, il che sarà presto importante.

Successivamente, e una delle prime cose che ho capito, è la sezione <[-[[<]<]++++++++++<]>[-]>. Questo appare più volte nel codice, ognuno con differenti schemi di redazione, ma non era difficile indovinare che tutte quelle istanze erano probabilmente lo stesso codice. Questo codice richiede tre zeri a sinistra del numero decimale sul nastro e il suo effetto è di ridurre il numero. L'ultima iterazione del ciclo metterà il valore 10 due celle a sinistra del numero, ma lo [-]pulisce.

Se il numero decimale era 0, non viene creato alcun 10 estraneo e la cella azzerata da [-]è la cifra più significativa. La testina si trova quindi sulla seconda cifra più significativa (motivo per cui sono necessarie almeno due cifre). La maggior parte delle istanze di questo frammento sono immediatamente seguite da [<<]>, il che pone la testa su una cella diversa da zero in condizioni normali e una cella zero se il numero decimale originale era zero. Sembra che in questo programma, la rappresentazione decimale di n-1sia usata per denotare n, in modo che il decremento 0sia catturato invece che decrementare -1.

La parte successiva inserisce i numeri da n-1 (n) a 0 (1) sul nastro:

>[                      until the number reaches zero:
  [                     for each digit:
    [>]>>[>]+[<]<<[<]>  create a placeholder for the next copy
    [                   while the original value of the digit is nonzero:
      <<+               add 1 to copy two cells left (to keep one copy)
      >>[>]>>[>]<+      go to new copy and increment that cell
      [<]<<[<]>-        go back to original digit and decrement
    ]                   (this is effectively the same as [<+>>+<-] but with the cells at variable locations)
  >]                    next digit
  >>[->]                cancel the placeholder 1s that were used for the new copy
  <[-[[<]<]++++++++++<]>[-]>[<<]> decrement
]
>[>]<[[-]<]      clean up the trash 10s on the tape while ending at a known location relative to the last number

Ora, questi numeri sono tutti sul nastro con due celle zero che li separano. <<<<<[<]<<ci mette nella cella finale del penultimo numero sul nastro, che è dove saremo in ogni iterazione del ciclo. Il ciclo termina quando sono stati gestiti tutti i numeri tranne l'originale.

All'inizio del ciclo, spostiamo il numero corrente (l'ultimo ancora sul nastro) di una cella a destra per avere spazio per diminuire, quindi proseguiamo e diminuiamo:

[>>>[>]<[[->+<]<]>>[>]<[-[[<]<]++++++++++<]>[-]>[<<]>

Se questo decremento non è insufficiente, si procede a convertire il numero in unario:

[[[>]>[>]+[<]<[-[[<]<]++++++++++<]>[-]>[<<]>]

Si noti che questo frammento ha un non chiuso [. Di conseguenza, il resto di questo ciclo viene ignorato se il numero era 0 (che rappresenta 1). Dopo la conversione in unario, cancelliamo i 10 rimanenti, trascinando la rappresentazione unaria con noi a sinistra:

>[>]<[[-]>+[>]<-<[<]<]+

Non me ne sono accorto fino a ora scrivendo questo, ma +alla fine di questo frammento è separato dalla rappresentazione unaria da un singolo 0. Fa anche parte della rappresentazione unaria: la sequenza 1011...11rappresenterà 0 mod k. Quanto segue <<<<<[<]>ci mette all'inizio del numero k+1, iniziando un nuovo ciclo.

Il ciclo interno qui "segna" ogni numero sul nastro con un 1 sulla cella immediatamente a destra, e usa la rappresentazione unaria come un orologio per determinare di quali numeri sono multipli k.

[
  [>]+             mark the current decimal number
  [[>]>]           move to end of decimal part of tape
  >[>]             move to 0 in middle of unary "clock"
  >[-<+>]          move the following 1 to the left if possible
  <[<]<            if a 1 was moved this will bring us back to a zero before the start of this "clock";
                   otherwise the looped move command doesn't move us at all and we are at the final 1
  [                if there was no gap (happens every kth iteration):
    >+[<]>>-       reset to original position
    <<<<<[[<]<]>>  go to number that was just marked
    [[-]+>]        replace digits with 0s (cell value 1)
    >[[>]>]<       go back to where we would be without this conditional
  ]
  <[[<]<]<[<]>     return to first unmarked number
]

In [[-]+>]quella sezione è stata l'ultima parte che ho capito. Prima di allora, ho pensato che il programma stesse facendo divisioni di prova, ma non riuscivo a vedere dove fosse usato il risultato.

Questo loop termina due celle a sinistra del numero all'estrema sinistra, >>>[[>]<->>]]rimuove i marker posizionati sul nastro e ci riporta nuovamente alla fine del nastro. Dopodiché >[[>]>]<<[[[-]<]<]rimuove l'orologio unario o, se questo intero segmento è stato ignorato, i rimanenti 10s. Il loop è impostato alla sua condizione iniziale con <<<[<]<<].

Dopo questo è solo leggendo se il numero di input è stato sostituito da 1 in qualsiasi momento:

>>>[>]<[-[[<]<]++++++++++<]>>                      do the check
[[>]+[------->++<]>.+.+++++.[---->+<]>+++.>>]      conditionally print "not "
>[>]+[------->++<]>++.++.---------.++++.--------.  unconditionally print "prime"

Fortunatamente, l'output effettivo non è stato affatto redatto.


"La notte è lunga che non trova mai il giorno." È ancora stanotte? : P
Stewie Griffin,

@StewieGriffin Non sono riuscito a farlo quella notte, e poi mi è passato di mente. Grazie per il promemoria.
Nitrodon,

Non credo che avrei potuto spiegare il mio codice così come hai fatto qui. Ottimo lavoro
Jo King,

5

Wolfram Language (Mathematica)

Crepa questa risposta .

f[x_]:=(p=ToString@Boole@PrimeQ@x;StringMatchQ[p&@@Infinity,RegularExpression@"(\
\n{}\b+, )?1"])

Provalo online!


Non è necessario lo scorrimento per leggere il codice :)
user202729,

Bello! Abbastanza diverso dalla soluzione prevista, quindi non lo rivelerò ancora.
Pavel,

@Pavel Che ne dici di questo ? O ancora "fondamentalmente lo stesso"?
user202729

Ecco un suggerimento: quel blob di grandi dimensioni non contiene né Boolemeno PrimeQ.
Pavel,

5

Brain-Flak, MegaTom

(({████){██[████)█>(({}))<>}<>{}███{}((██({}))█████{}]██)({}(<>))<>{(({})){({}[()])<>}{}}{}<>([{}()]{})██[██()██(()█[()]██{}██}{}<>{})
(({})<>){([[]]{})<>(({}))<>}<>{}{}{{}(([]({}))[({}[{}])])({}(<>))<>{(({})){({}[()])<>}{}}{}<>([{}()]{})}([][()])((){[()](<{}>)}{}<>{})

Provalo online!

Questo programma esegue divisioni di prova da n-2 a 1, quindi emette 1 se e solo se questo è terminato con il fattore 1.


4

8086 DOS COM di Joshua

xxd rappresentazione, a causa di codifiche e byte null e altri elementi spaventosi:

00000000: 31c0 b90a 0031 dbbe 8100 ac3c 0d74 3c3c  1....1.....<.t<<
00000010: 2075 f7ac 3c0d 7410 2c30 7c2f 3c09 7f2b   u..<.t.,0|/<..+
00000020: 93f7 e193 01c3 ebeb 83fb 027c 19c6 0653  ...........|...S
00000030: 0159 b902 0039 d974 1289 d831 d2f7 f109  .Y...9.t...1....
00000040: d274 0341 ebef c606 5301 4eb4 09ba 5301  .t.A....S.N...S.
00000050: cd21 c341 0d0a 24                        .!.A..$

Prima hai smontato il poliziotto manualmente, poi assemblato usando lo yasm. Alcuni byte sono stati corrotti dal conerter usato da Joshua, ma li ho appena trattati come byte redatti. Sono sicuro del 99,72% sul loro contenuto reale. Tuttavia, non dovrei impiegare molto a risolverlo se sbaglio. Godere:

; A COM file is just a 16-bit flat binary
; loaded at 0x100 in some segment by DOS

org 0x100
bits 16

; Unsurprisingly, we start by converting
; the commandline string to a number. During
; the conversion, SI is a pointer to the
; string, CX is the base, and BX holds the
; partial result
parse_input:
; We'll read the input character by character
; into AL, but we need the resulting digit as
; a 16-bit number. Therefore, initialise AX to
; zero.
    xor ax, ax
    mov cx, 10
    xor bx, bx
; When a DOS program is loaded, it's preceded
; in memory by the Program Segment Prefix,
; which holds the commandline arguments at
; offset 0x81, terminated by a carriage return
    mov si, 0x81

.skip_prog_name:
; Load a character and move the pointer
    lodsb
; If we find the terminator here, the program
; was not given any arguments.
    cmp al, 13
    je finish

    cmp al, ' '
    jne .skip_prog_name

.input_loop:
    lodsb
    cmp al, 13
    je got_input

; If the ASCII value of the character is less
; than the one of '0', error out. Adjust the
; value in AL so that it holds the digit
; itself. This exploits the fact that the
; comparison instruction is just a subtraction
; that throws away the actual result.
    sub al, '0'
    jl finish

; If we have a value larger than 9, this
; character wasn't a digit.
    cmp al, 9
    jg finish

; Multiply the intermediate result by 10 and
; add the new digit to it.

    xchg ax, bx
    mul cx
    xchg ax, bx
    add bx, ax
    jmp .input_loop

got_input:
; The loop below would go haywire when given a
; zero or a one, so make them a special case.
    cmp bx, 2
    jl composite

; Patch the output string to say that it's
; prime
    mov byte[outstr], 'Y'

; BX = number being checked
; CX = loop counter, potential divisor of BX
    mov cx, 2

.loop:
; If CX = BX, we looked everywhere and couldn't
; find a divisor, therefore the number is prime
    cmp cx, bx
    je finish

; DIV takes DX:AX as a 32-bit number for the
; dividend. We don't want nor need the extra
; precision, so we set DX to 0.
    mov ax, bx
    xor dx, dx
    div cx

; DX now contains the remainder. To check if
; it's 0, we perform some noop operation, that
; happens to set the flags appropriately. AND
; and OR are commonly used for this purpose.
; Because of what's presumably a bug in the
; encoder used by Joshua, I do not yet know
; which for certain. However, I can make an
; educated guess. All other instances of the
; bug happened with a codepoint below 32.
; Moreover, no other bytes from that range
; occur in the code. Because an AND would be
; encoded as an exclamation mark, while OR -
; - as a tab, I am highly confident that Joshua
; used an OR.
    or dx, dx
    jz composite

; Increment the counter and loop again!
    inc cx
    jmp .loop

composite:
    mov byte[outstr], 'N'

finish:
    mov ah, 9
    mov dx, outstr
    int 0x21
    ret

outstr:
    db 'A', 13, 10, '$'

L'unica differenza tra le mie era quella bx < 2di finire piuttosto che composito. Cordiali saluti, la corruzione era dovuta originariamente all'utilizzo di X come personaggio maschera e al non corretto tutto quando si passa a █.
Giosuè,

@Joshua All'inizio ho usato anche Finish, ma poi ho ricordato che è necessario maneggiare correttamente 1. A proposito della corruzione - questo è uno degli scenari che ho immaginato
NieDzejkob il

3

Gelatina

Crepa questa risposta.

25██26█966836897364918299█0█1█65849159233270█02█837903312854349029387313█ị██v
250126,9668368973649182994001,658491592332700020837903312854349029387313ṖịØJv

Provalo online!


Spiegazione:

Guardando e v, penso di costruire un elenco di numeri, di inserirlo in qualche elenco e di valutarlo.

Il modo "banale" di controllare la primalità in Jelly è ÆP, quindi (se riesce a spaccare la sottomissione):

  • L'elenco da indicizzare deve contenere Æe P.
  • L'elenco degli indici deve essere modulo congruente 256con [14, 81].

Quindi ... l'elenco all'inizio del programma congruente al [14, 81, 49]mod 256 ( TIO ) e apre l'ultimo elemento.


3

sh + coreutils

Crepa questa risposta .

eecs c "██████WyAkKHNoIC1jICJg█WNobyBabUZqZEc5eWZIUnlJQ2█2SnlBblhHNG5m██JoYVd3Z0t6SjhkMk1nTFhjSyB8YmFzZTY0IC1kYCIpIC1lcSAxIF0K█b█se6███d`"
exec sh -c "`echo WyAkKHNoIC1jICJgZWNobyBabUZqZEc5eWZIUnlJQ2M2SnlBblhHNG5mSFJoYVd3Z0t6SjhkMk1nTFhjSyB8YmFzZTY0IC1kYCIpIC1lcSAxIF0K|base64 -d`"

No Provalo online! questa volta a causa di alcuni problemi . Tuttavia puoi usare jdoodle .

Restituisce per codice di uscita. 0(successo) per prime, 1(errore) per composito.

Il comando effettivo eseguito è

factor|tr ':' '\n'|tail +2|wc -w

Come rompere

  1. Guarda il codice, riconosci Base64.
  2. Scopri come usare il base64comando.
  3. Sappi che +è un carattere base64 valido.
  4. Prova a decodificare .
  5. Applica il wrapper sh -c "`echo ...|base64 -d`"al programma originale .
  6. Genera base64 nidificato dai comandi .

Metodo corretto. "Alcuni problemi" risulta non essere tutte le macchine a conoscenza tail +n. Quando ho provato la tua crepa sulla macchina al lavoro, me ne sono lamentato. Hai smascherato il codice corretto quindi ... :(
Joshua,

3

Ottava , 86 byte, Stewie Griffin .

@(x)eval([(str2num(cell2mat([cellstr(reshape('0█1███1█0█0█00',████))])')'█')','(x)'])
@(x)eval([(str2num(cell2mat([cellstr(reshape('04141113040800',2,[]))])')+'e')','(x)'])

Provalo online!

Questo è stato divertente! Ho lottato con questo per un bel paio di giorni.

Il primo indizio riconosceva eval([...,'(x)'])come costruzione creando una chiamata alla isprimefunzione, come concatenazione di intse charimplicitamente convertire la matrice a char, quindi il ...bisogno di essere sia isprimeo una matrice che ha i valori ASCII isprime, [105, 115, 112, 114, 105, 109, 101].

Il resto è stato solo sfogliare la documentazione per capire che reshapepuò assumere una dimensione sconosciuta [], anche se suppongo che avrei potuto fare reshape(...,2, 7)allo stesso numero di byte.

Usare +'e'(101) invece di +'d'(100) è stato un bel tocco che mi ha lanciato per qualche altro minuto fino a quando ho notato che le ultime cifre (non offuscate) erano 00piuttosto che 01, e con ciò è stato facile.


2

JavaScript

x=>{if(x<4)return(!0);for(y=x>>>Math.log10(p=████;--y-1;(p=x/y%1)████if(██&&(███))break████return(███)}
x=>{if(x<4)return(!0);for(y=x>>>Math.log10(p=2-1);--y-1;(p=x/y%1)){;;if(!p&&(1<2))break;;;}return(!!p)}

Provalo online!

Dubito che sia esattamente quello che avevi in ​​mente, ma funziona.


2

> <> , Esolanging fruit

:1@v>~~:?1n;█$-1<█?=2:}*{█@:$@:

per

:1@v>~~:?1n;
$-1</?=2:}*{%@:$@:

Provalo online!

L'uso intelligente della redazione di una nuova riga mi ha confuso per un po '. Tuttavia, non sembra funzionare per 1 o 2.


Bello. Qualsiasi di ^, v, /, o \ per il secondo blocco vuoto hanno lavorato lì. Ora vorrei aver coperto *invece di /.
Esolanging Fruit,

2

Java (OpenJDK 8) , Magic Octopus Urn

class X{public static void main(String[]args){System.out.println(new String(████████[Integer.parseInt(args[0])]).matches("█████████████")?███);}}
class X{public static void main(String[]args){System.out.println(new String(new char[Integer.parseInt(args[0])]).matches(".?|(..+?)\\1+")?0:1);}}

Provalo online!

Il codice è preso da RosettaCode e spiegato su SO .


Non avevo idea che fosse così popolare hah! Ho avuto questo nella mia tasca posteriore per molto tempo. L'ho onestamente rubato da un file di utilità che ho avuto da allora ... Cazzo ... 2014?
Magic Octopus Urn

2

Python 3 , 44 byte, osuka_

p=lambda x,i=2:i>=x or(x%i and p(x,i+1))or 0

Provalo online!

Non funziona quando x <2. Il or 0può essere sostituito con >0{2 spaces}o anche 4 spazi

Per il problema x <2, dato che i>=xdeve essere messo in primo piano (altrimenti ci sarà un ciclo infinito), e il valore i>=xrestituisce immediatamente immediatamente quando x <2, quindi penso che non sia una soluzione.


Quindi, a quanto pare, il mio codice non funziona neanche con x <2. Ops. (Probabilmente l'ho appena provato con il range (2, ...), perché sono stupido)
osuka_

2

M, Dylnan

ÆPø“;;“»VOḣ2S⁵++3Ọ;”Pv

Questa probabilmente non era la soluzione prevista.

Provalo online!

Come funziona

ÆP è il test di primalità incorporato.

øesseri una nuova catena niladica. Poiché il valore restituito precedente (il risultato di ÆP) non rientra nell'ambito, questo lo stampa implicitamente.

“;;“»valuta l'elenco delle stringhe ["< Aalst" ""]e Vcerca di valutarle. stenta di dividere il suo argomento in blocchi di lunghezza 0 , causando l'arresto anomalo dell'interprete M, sopprimendo l'ulteriore output.


Soluzione non voluta ma carina. Aggiornerà presto i post su crack. Se dicessi la parola "zoo" ti porterebbe a un'altra possibile soluzione?
dylnan,

Sembra un infinito complesso.
Dennis,


1

Python 3 , user71546

import random
def f(z):
 if z<4:return z>>1
 d,s,n,e,c=~-z,0,z,0,50
 while not d&1:d//=2;s+=1
 while n>0:n//=2;e+=1
 random.seed()
 while c>0:
  a=0
  while a<2or a>z-1:
   a,b=0,e
   while b>0:a=a*2+random.randint(0,1);b-=1
  x,r=pow(a,d,z),~-s
  if ~-x and x!=~-z:
   while r>0:
    x,r=pow(x,2,z),~-r
    if not ~-x:return 0
    elif x==~-z:break
   else:return 0
  c-=1
 else:return 1

Provalo online!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.