Policiers et voleurs: Primality expurgée (Thread 'Thread)


9

Ceci est le fil des voleurs. Le fil des flics est ici .

Votre défi est de prendre une soumission non fissurée du fil des flics et d'essayer de trouver le programme original non expurgé. Veuillez commenter la soumission du policier lorsque vous avez craqué son code.

Réponses:


6

brainfuck , Jo King

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

Essayez-le en ligne!

Cela met en œuvre le tamis d'Ératosthène.

L'initiale >>>>>+>,[>++++++[-<-------->]<+>,]entre chaque chiffre sous forme de code de caractère et soustrait 47 pour le mettre dans la plage 1-10. Cela permet une valeur de cellule de 0 pour indiquer l'espacement entre les nombres. Au +>début de cette section, le nombre doit être d'au moins deux chiffres, ce qui sera important bientôt.

Ensuite, et l'une des premières choses que j'ai découvert, c'est la section <[-[[<]<]++++++++++<]>[-]>. Cela apparaît plusieurs fois dans le code, chacun avec des schémas de rédaction différents, mais il n'était pas difficile de deviner que toutes ces instances étaient probablement le même code. Ce code nécessite trois zéros à gauche du nombre décimal sur la bande, et son effet est de décrémenter le nombre. La dernière itération de la boucle mettra la valeur 10 deux cellules à gauche du nombre, mais le [-]nettoie.

Si le nombre décimal était 0, il n'y a pas de 10 étranger créé et la cellule mise à zéro par [-]est le chiffre le plus significatif. La tête de bande se trouve alors au deuxième chiffre le plus significatif (c'est pourquoi au moins deux chiffres sont nécessaires). La plupart des instances de cet extrait de code sont immédiatement suivies de [<<]>, ce qui place la tête sur une cellule non nulle dans des conditions normales et une cellule nulle si le nombre décimal d'origine était zéro. Il semble que dans ce programme, la représentation décimale de n-1est utilisée pour désigner n, de sorte que la décrémentation de 0est capturée au lieu de la décrémentation de -1.

La partie suivante met les nombres de n-1 (n) à 0 (1) sur la bande:

>[                      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

Maintenant, ces nombres sont tous sur la bande avec deux cellules nulles les séparant. <<<<<[<]<<nous place à la dernière cellule de l'avant-dernier numéro de la bande, où nous serons à chaque itération de la boucle. La boucle se termine lorsque tous les numéros sauf l'original ont été traités.

Au début de la boucle, nous déplaçons le numéro actuel (le dernier encore sur la bande) d'une cellule vers la droite pour avoir de la place pour décrémenter, puis continuons et décrémentons:

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

Si ce décrément n'a pas dépassé, nous procédons à la conversion du nombre en unaire:

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

Notez que cet extrait a un fichier non fermé [. Par conséquent, le reste de cette boucle est ignoré si le nombre était 0 (représentant 1). Après la conversion en unaire, nous effaçons les 10 restants, en faisant glisser la représentation unaire avec nous vers la gauche:

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

Je n'ai pas remarqué jusqu'à présent en écrivant ceci, mais +à la fin de cet extrait est séparé de la représentation unaire par un seul 0. Il fait également partie de la représentation unaire: la séquence 1011...11représentera 0 mod k. Ce qui suit <<<<<[<]>nous place au début du nombre k+1, commençant une nouvelle boucle.

La boucle intérieure ici "marque" chaque nombre sur la bande avec un 1 sur la cellule immédiatement à droite, et utilise la représentation unaire comme horloge pour déterminer quels nombres sont des multiples de 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
]

Le [[-]+>]dans cette section était la dernière partie que j'ai compris. Avant cela, je supposais que le programme ne faisait que des divisions d'essai, mais je ne pouvais pas voir où le résultat était utilisé.

Cette boucle termine deux cellules à gauche du nombre le plus à gauche, et >>>[[>]<->>]]supprime les marqueurs placés sur la bande et nous ramène à la fin de la bande. Après cela, >[[>]>]<<[[[-]<]<]supprime l'horloge unaire ou, si tout ce segment a été ignoré, les 10 restants. La boucle est mise à sa condition de départ avec <<<[<]<<].

Après cela, il suffit de lire si le numéro d'entrée a été remplacé par 1 à tout moment:

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

Heureusement, la production réelle n'a pas du tout été expurgée.


"La nuit est longue qui ne trouve jamais le jour." Est-ce encore ce soir? : P
Stewie Griffin

@StewieGriffin Je n'ai pas pu le faire cette nuit-là, puis ça m'a tout simplement glissé. Merci pour le rappel.
Nitrodon

Je ne pense pas que j'aurais pu expliquer mon propre code aussi bien que vous l'avez fait ici. Très bon travail.
Jo King

5

Wolfram Language (Mathematica)

Cracks cette réponse .

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

Essayez-le en ligne!


Pas de défilement nécessaire pour lire le code :)
user202729

Agréable! Tout à fait différent de la solution envisagée, donc je ne le révélerai pas encore.
Pavel

@Pavel Et à ce sujet ? Ou encore "fondamentalement le même"?
user202729

Voici un indice: ce grand blob ne contient ni Boolenon PrimeQ.
Pavel

5

Brain-Flak, MegaTom

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

Essayez-le en ligne!

Ce programme effectue des divisions d'essai de n-2 à 1, puis sort 1 si et seulement si cela se termine par le facteur 1.


4

8086 DOS COM par Joshua

xxd représentation, à cause des encodages et des octets nuls et autres trucs effrayants:

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

D'abord démonté le flic manuellement, puis assemblé à l'aide de yasm. Certains octets ont été corrompus par le conerter utilisé par Joshua, mais je viens de les traiter comme des octets caviardés. Je suis certain à 99,72% de leur contenu réel. Mais cela ne devrait pas prendre longtemps si je me trompe. Prendre plaisir:

; 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, '$'

La seule différence entre le mien était bx < 2de finir plutôt que de composite. Pour info, la corruption était due à l'origine à l'utilisation de X comme personnage de masque et à ne pas tout réparer correctement lors du passage à █.
Joshua

@Joshua J'ai également utilisé la finition au début, mais je me suis ensuite souvenu que la manipulation correcte de 1 était nécessaire. À propos de la corruption - c'est l'un des scénarios que j'imaginais
NieDzejkob

3

Gelée

Cracks cette réponse.

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

Essayez-le en ligne!


Explication:

En regardant et v, je pense à construire une liste de nombres, à la trouver dans une liste et à l'évaluer.

La façon "triviale" de vérifier la primauté dans Jelly est ÆP, donc (si elle peut casser la soumission):

  • La liste à indexer doit contenir Æet P.
  • La liste des indices doit être modulo congruente 256avec [14, 81].

Donc ... la liste au début du programme est conforme au [14, 81, 49]mod 256 ( TIO ) et affiche le dernier élément.


3

sh + coreutils

Cracks cette réponse .

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

Non Essayez-le en ligne! cette fois en raison de certains problèmes . Cependant, vous pouvez utiliser jdoodle .

Renvoie par code de sortie. 0(succès) pour le premier, 1(erreur) pour le composite.

La commande réellement exécutée est

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

Comment casser

  1. Regardez le code, reconnaissez Base64.
  2. Apprenez à utiliser la base64commande.
  3. Sachez que +c'est un caractère base64 valide.
  4. Essayez de décoder .
  5. Appliquez le wrapper sh -c "`echo ...|base64 -d`"au programme d'origine .
  6. Générez une base64 imbriquée à partir de commandes .

Méthode correcte. "Certains problèmes" ne sont pas connus de toutes les machines tail +n. Quand j'ai essayé votre crack sur la machine au travail, il s'en est plaint. Vous avez démasqué le bon code alors ... :(
Joshua

3

Octave , 86 octets, 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)'])

Essayez-le en ligne!

C'était amusant! J'ai lutté avec ça pendant quelques bons jours.

Le premier indice a été reconnaissant eval([...,'(x)'])comme la construction la création d' un appel à la isprimefonction, concaténation intset charconvertit implicitement le tableau à char, de sorte que le ...besoin d'être soit isprimeou un tableau qui avait les valeurs ASCII isprime, [105, 115, 112, 114, 105, 109, 101].

Le reste était simplement en train de fouiller dans la documentation pour comprendre qui reshapepeut prendre une dimension inconnue [], bien que je suppose que j'aurais pu le faire reshape(...,2, 7)avec le même nombre d'octets.

Utiliser +'e'(101) au lieu de +'d'(100) était une touche agréable qui m'a jeté pendant quelques minutes jusqu'à ce que je remarque que les derniers chiffres (non obscurcis) étaient 00plutôt que 01, et avec cela, c'était 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)}

Essayez-le en ligne!

Je doute que ce soit exactement ce que vous aviez en tête, mais cela fonctionne.


2

> <> , Esolanging fruit

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

à

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

Essayez-le en ligne!

L'utilisation intelligente de la rédaction d'une nouvelle ligne m'a un peu dérouté. Ne semble cependant pas fonctionner pendant 1 ou 2.


Agréable. Tout de ^, v, /ou \ pour la seconde ébauche aurait pu y avoir travaillé. J'aimerais maintenant avoir couvert le *au lieu du /.
Esolanging Fruit

2

Java (OpenJDK 8) , Urne Magic Octopus

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

Essayez-le en ligne!

Le code est tiré de RosettaCode et expliqué sur SO .


Je ne savais pas que c'était ce hah populaire! J'avais ça dans ma poche arrière depuis longtemps. Honnêtement, je l'ai volé dans un fichier utilitaire que j'ai depuis comme ... Jeez ... 2014?
Urne de poulpe magique le

2

Python 3 , 44 octets, osuka_

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

Essayez-le en ligne!

Ne fonctionne pas lorsque x <2. Le or 0peut être remplacé par >0{2 spaces}ou même 4 espaces

Pour le problème x <2, puisque i>=xdoit être placé à l'avant (sinon il y aura une boucle infinie), et le i>=xretourne vrai immédiatement lorsque x <2, donc je pense que ce n'est pas une solution.


Donc, il s'avère que mon code ne fonctionne pas non plus avec x <2. Oops. (Je l'ai probablement juste testé avec range (2, ...), parce que je suis stupide)
osuka_

2

M, dylnan

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

Ce n'était probablement pas la solution envisagée.

Essayez-le en ligne!

Comment ça fonctionne

ÆP est le test de primalité intégré.

øêtres une nouvelle chaîne niladique. Étant donné que la valeur de retour précédente (le résultat deÆP ) est hors de portée, cela l'imprime implicitement.

“;;“»évalue la liste des chaînes ["< Aalst" ""]et Vessaie de les évaluer . sessaie de diviser son argument en morceaux de longueur 0 , ce qui provoque l'interruption de l'interpréteur M, supprimant ainsi la sortie.


Solution non prévue mais agréable. Mettra à jour le message à craquer bientôt. Si je disais le mot «zoo», cela vous mènerait-il à une autre solution possible?
dylnan

Hm, cela ressemble à l'infini complexe.
Dennis


1

Python 3 , utilisateur 71546

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

Essayez-le en ligne!

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.