Le compteur d'octets répétitifs


19

Votre tâche consiste à écrire un programme comptage / fonction non vide de l' octet L , qui, lorsqu'ils sont répétés M fois, vérifie si un nombre entier positif donné N est égal à L × M .

Vous devriez, en théorie, prendre en charge un nombre arbitraire de répétitions (une valeur entière positive arbitraire de M ), mais c'est bien si, en raison des limitations du langage, il ne peut pas fonctionner au-delà d'un certain seuil. La lecture du code source de votre programme ou l'accès aux informations le concernant sont strictement interdits .

Pour fournir une sortie, vous devez choisir une valeur cohérente pour l'un des états (vrai ou faux) et utiliser toute autre sortie possible (pas nécessairement cohérente) pour l'autre état ( discussion ).

Vos réponses seront notées par la longueur L de votre programme initial (en octets), avec moins d'octets étant mieux.

Exemple

Disons que votre programme (initial) l'est ABCDE. Alors:

  • ABCDE(1 répétition) devrait vérifier si l'entrée est égale à 5 .
  • ABCDEABCDE(2 répétitions) devrait vérifier si l'entrée est égale à 10 .
  • ABCDEABCDEABCDE(3 répétitions) devrait vérifier si l'entrée est égale à 15 . Etc...

Le score de cet exemple de code serait de 5 , car la source initiale est longue de 5 octets.


Juste pour clarifier: le code source de longueur Lconcaténée après lui-même Mdevrait renvoyer si son entrée Nest égale àL*M ?

Réponses:


12

Gelée , 1 octet

La sortie est 0 pour une correspondance, différente de zéro pour une non-correspondance.

Essayez-le en ligne!

Comment ça fonctionne

Cela profite du format de sortie trop libéral. La répétition de M fois diminue simplement les M fois d' entrée , le résultat sera donc nul si et seulement si l'entrée est LM , où L = 1 .


Oh mon dieu, je ne l'ai pas vu venir ... ( inb4 tout le monde le porte à d'autres esolangs ... )
M. Xcoder

J'avais une réponse de 0 octet à l'esprit, mais, eh, quine . : P
Erik the Outgolfer

Ma première pensée. Battu de 23 minutes :(
Khuldraeseth na'Barya

11

Haskell, 8 octets

(-8+).id

Essayez-le en ligne!

Comme beaucoup d'autres réponses, il renvoie 0 pour la vérité et non 0 pour la fausse en soustrayant à plusieurs reprises la longueur du code du numéro d'entrée.


J'étais si près de bricoler pour arriver à ça ...
totalement humain

8

Rétine , 21 20 octets

\d+
*
^$
_
^_{20}

_

Essayez-le en ligne! Répétez simplement la partie dans la fenêtre Code pour voir comment elle gère les multiples.

Donne 0les entiers multiples et positifs corrects pour tout le reste.

Explication

Regardons d'abord le programme unique:

\d+
*

Cela convertit un nombre décimal en unaire (en utilisant _comme chiffre unaire).

^$
_

Si la chaîne est vide (ce qui ne peut pas se produire à ce stade, car l'entrée est garantie positive), nous la remplaçons par une seule _.

^_{20}

Maintenant, nous nous débarrassons des 20 premiers traits de soulignement. Si l'entrée était 20, cela se traduit par une chaîne vide.

_

Et enfin, nous comptons le nombre de soulignements dans le résultat, qui est nul si l'entrée était 20.


Maintenant, que se passe-t-il lorsque nous répétons le code source. Étant donné que nous n'insérons pas de saut de ligne lorsque nous rejoignons les programmes, la première ligne ira juste à la fin de la dernière ligne, nous l'obtenons lorsque le double du programme:

\d+
*
^$
_
^_{20}

_\d+
*
^$
_
^_{20}

_

Maintenant, au lieu de compter les soulignés, nous nous retrouvons avec l'étape suivante:

_\d+
*

Cette étape ne fait rien, car il n'y a plus de chiffres dans la chaîne de travail à ce stade, donc l'expression régulière ne peut pas correspondre.

^$
_

Maintenant, cette étape devient pertinente. Si l'entrée était un plus petit multiple de 20, la chaîne a été vidée par la copie précédente du code source. Dans ce cas, nous le transformons en un seul soulignement, qui, nous le savons, ne pourra plus jamais être transformé en chaîne vide par notre programme. De cette façon, nous nous assurons que seul le M e multiple est accepté (et pas tous les multiples jusqu'au M e).

^_{20}

Nous supprimons à nouveau les 20 premiers soulignements. Ainsi, M répétitions du code source supprimera si possible 20 millions de soulignements de la chaîne.

_

Et lorsque nous arrivons à la fin du programme, nous comptons toujours les traits de soulignement pour que les entrées valides donnent zéro.


6

Fragment de code machine x86 32 bits, 1 octet

48                      dec    eax

Entrée dans EAX, sortie dans EAX: 0 pour vrai, non nul pour faux. (Laisse également le drapeau ZF défini sur true, non défini sur false, afin que vous puissiez je was_equal). En "bonus", vous n'avez pas à vous soucier de l'emballage; Le x86 32 bits ne peut traiter que 4 Go de mémoire, vous ne pouvez donc pas faire M assez grand pour envelopper tout autour et trouver 1 == 2**32 + 1ou quelque chose.

Pour créer une fonction appelable, ajoutez une 0xC3 retinstruction après avoir répété 0x48M fois. (Non compté dans le nombre total, car de nombreuses langues doivent répéter uniquement le corps de la fonction ou une expression pour pouvoir rivaliser).

Appelable depuis GNU C avec l' attribut de fonction x86 du prototype __attribute__((regparm(1))) int checkeqM(int eax); GNU Cregparm , comme -mregparm, utilise EAX pour passer le premier argument entier.

Par exemple, ce programme complet prend 2 arguments, et JITs M copies de l'instruction + a retdans un tampon, puis l'appelle en tant que fonction. (Nécessite un tas exécutable; compiler avec gcc -O3 -m32 -z execstack)

/******* Test harness: JIT into a buffer and call it ******/
// compile with gcc -O3 -no-pie -fno-pie -m32 -z execstack
// or use mprotect or VirtualProtect instead of -z execstack
// or mmap(PROT_EXEC|PROT_READ|PROT_WRITE) instead of malloc

// declare a function pointer to a regparm=1 function
// The special calling convention applies to this function-pointer only
// So main() can still get its args properly, and call libc functions.
// unlike if you compile with -mregparm=1
typedef int __attribute__((regparm(1))) (*eax_arg_funcptr_t)(unsigned arg);

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
    if (argc<3) return -1;
    unsigned N=strtoul(argv[1], NULL, 0), M = strtoul(argv[2], NULL, 0);

    char *execbuf = malloc(M+1);   // no error checking
    memset(execbuf, 0x48, M);     // times M  dec eax
    execbuf[M] = 0xC3;            // ret
    // Tell GCC we're about to run this data as code.  x86 has coherent I-cache,
    // but this also stops optimization from removing these as dead stores.
    __builtin___clear_cache (execbuf, execbuf+M+1);
     //   asm("" ::: "memory");  // compiler memory barrier works too.

    eax_arg_funcptr_t execfunc = (eax_arg_funcptr_t) execbuf;
    int res = execfunc(N);
    printf("%u == %u  =>  %d\n", N,M, res );
    return !!res;   // exit status only takes the low 8 bits of return value
}

les exécutables non PIE sont chargés plus bas dans la mémoire virtuelle; peut faire un plus grand malloc contigu.

$ gcc -g -O3 -m32 -no-pie -fno-pie -fno-plt -z execstack coderepeat-i386.c
$ time ./a.out 2747483748 2747483748   # 2^31 + 600000100 is close to as big as we can allocate successfully
2747483748 == 2747483748  =>  0

real    0m1.590s     # on a 3.9GHz Skylake with DDR4-2666
user    0m0.831s
sys     0m0.755s

$ echo $?
0

 # perf stat output:
       670,816      page-faults               #    0.418 M/sec                  
 6,235,285,157      cycles                    #    3.885 GHz                    
 5,370,142,756      instructions              #    0.86  insn per cycle         

Notez que GNU C ne supporte pas les objets de tailles plus grand que ptrdiff_t(signé 32 bits), mais mallocet memsetfaire encore du travail, de sorte que ce programme réussisse.

Fragment de code machine ARM Thumb, 2 octets

 3802            subs    r0, #2

Le premier argument r0et la valeur de retour dans r0est la convention d'appel ARM standard. Cela définit également des indicateurs (le ssuffixe). Fait amusant; la version sans réglage de drapeau subest une instruction large de 32 bits.

L'instruction de retour que vous devez ajouter est bx lr.

Fragment de code machine AArch64, 4 octets

d1001000        sub     x0, x0, #0x4

Fonctionne pour les entiers 64 bits. Entrée / sortie dans x0, selon la convention d'appel standard. int64_t foo(uint64_t);

AArch64 n'a pas (encore) de mode Thumb, donc 1 instruction est la meilleure que nous puissions faire.


Remarque pour tous ceux qui rencontrent ceci: l'appel à __builtin___clear_cacheest uniquement nécessaire parce que vous exécutez la mémoire que vous avez obtenue malloc. Si vous avez obtenu la mémoire à la mmapplace, l'optimisation ne se produit pas.
Joseph Sible-Reinstate Monica

4

V , 16 (ou 1) octets

Réponse ennuyeuse:

<C-x>

un octet.

Réponse moins ennuyeuse:

uÓ^$/0
16Ø^a$

Essayez-le en ligne!

Hexdump:

00000000: 75d3 5e24 2f30 0a31 3601 d85e 1261 240a  u.^$/0.16..^.a$.

J'ai en fait écrit ceci environ 5 minutes après la sortie du défi. Il m'a fallu 30 minutes pour patcher cette horrible pile de code spaghetti que j'appelle une langue .





2

Brain-Flak , 24 octets

({}[(((()()()){}){}){}])

Essayez-le en ligne!

Renvoie 0pour égal et autre chose pour différent.

Comment ça fonctionne:

({} #pop the top of the stack
  [(((()()()){}){}){}] #subtract 24
) #push the result.

Ce ntemps d' exécution du code sera soustrait n * 24de l'entrée, donnant 0 uniquement lorsque l'entrée = n*24.



2

TI-Basic (série 83), 4 octets

:Ans-4

Prend l'entrée Ans: par exemple, vous pouvez taper 17:prgmCODEGOLFpour exécuter ceci avec une entrée de 17. Imprime (et renvoie Ans) la valeur 0si l'entrée est égale à L × M , et une valeur différente de zéro sinon.

Notez que le :fait partie du code, donc si vous entrez ceci dans l'éditeur de programme, vous devriez voir

PROGRAM:CODEGOLF
::Ans-4

si vous le saisissez une fois et

PROGRAM:CODEGOLF
::Ans-4:Ans-4:An
s-4

si vous le saisissez trois fois.



1

Befunge-98 , 15 octets

]#<@.-&+
>fv
v+

Essayez-le en ligne!

Essayez-le doublé!

Utilise 0 pour égal et toute autre chose pour inégale.

Explication:

Ce code répété plusieurs fois ressemblera à ceci:

]#<@.-&+
>fv
v+]#<@.-&+
>fv
v+]#<@.-&+
>fv
 .
 .
 .
v+]#<@.-&+
>fv
v+
  1. ]virage à droite. Envoie l'IP vers le bas.

  2. >se déplacer vers l'est. Envoie le droit IP.

  3. f pousser un 16.

  4. vse déplacer vers le sud. Envoie l'IP vers le bas. Si c'est la dernière fois, passez à l'étape 8.

  5. ]virage à droite. Envoie l'IP à gauche.

  6. +ajouter. Ajoute le 16 en haut de la pile.

  7. vse déplacer vers le sud. Envoie l'IP vers le bas. Passez à l'étape 2.

  8. <déplacer vers l'ouest. Envoyez l'IP à gauche.

  9. #sauter. sauter par-dessus ]et enrouler jusqu'à la fin.

  10. +ajouter. Ajoute le 16 en haut de la pile.

  11. &contribution. Appuyez sur un numéro de l'utilisateur.

  12. -soustraire. obtenir la différence de somme sur laquelle nous travaillions et l'entrée.

  13. .impression. Imprimez le résultat.

  14. @ fin.



1

Fusain , 13 octets

PI⁼Iθ×¹³L⊞Oυω

Essayez-le en ligne! Sur la base de ma réponse, je double la source, vous doublez la sortie! Explication:

         ⊞Oυω   Push empty string to predefined empty list
        L       Take the length
     ×¹³        Multiply by 13
  ⁼Iθ           Compare to the input
 I              Cast to string
P               Print without moving the cursor

Gère la sortie 1pour la vérité et la 0fausse. Répétitions ultérieures comparer l'entrée contre 13, 26, 39, 52etc. , mais à chaque fois que la réponse est surchargée alors que la réponse finale est considérée.


1

JavaScript ES6, 32 octets

((f=k=>n=>n>0?n==k:f(k+32))(32))

si vrai, 0 et faux comme les autres, 31 octets

(f=k=>n=>n>0?n-k:_=>f(k+_))(31)

console.log([
    ((f=k=>n=>n>0?n==k:f(k+32))(32)) (31),
    ((f=k=>n=>n>0?n==k:f(k+32))(32)) (32),
    ((f=k=>n=>n>0?n==k:f(k+32))(32)) (33),
    ((f=k=>n=>n>0?n==k:f(k+32))(32)) (64),
    ((f=k=>n=>n>0?n==k:f(k+32))(32))((f=k=>n=>n>0?n==k:f(k+32))(32)) (32),
    ((f=k=>n=>n>0?n==k:f(k+32))(32))((f=k=>n=>n>0?n==k:f(k+32))(32)) (63),
    ((f=k=>n=>n>0?n==k:f(k+32))(32))((f=k=>n=>n>0?n==k:f(k+32))(32)) (64),
    ((f=k=>n=>n>0?n==k:f(k+32))(32))((f=k=>n=>n>0?n==k:f(k+32))(32))((f=k=>n=>n>0?n==k:f(k+32))(32)) (96)
]);


1

MIPS, 4 octets

Utilise $a0comme argument et valeur de retour.

0x2084fffc    addi $a0, $a0, -4

MIPS, 8 octets (en utilisant la convention d'appel MIPS)

0x2084fff8    addi $a0, $a0, -8
0x00041021    move $v0, $a0

x86, 5 octets

Ceci est ma première réponse x86, donc les commentaires sont les bienvenus. Utilise la convention _fastcall avec ecx comme premier argument.

83 e9 05                sub    $0x5,%ecx
89 c8                   mov    %ecx,%eax

Peter Cordes a une solution à 1 octet dans les commentaires.


Commentaire de Brainfuck : La partie difficile est d'obtenir que brainfuck retourne une seule valeur. Sinon, quelque chose comme ça serait facile.

- >,[-<->] < .

1
Votre fragment de code x86 aurait la même taille pour les entiers 32 bits, pas besoin de limiter à 8. Mais si vous avez utilisé une convention d'appel personnalisée (arg en AL, retval ailleurs,), vous pouvez utiliser la spéciale AL de 2 octets encodage sub $4, %al/ mov %al, %dl. Ou revenez toujours dans AL / EAX et vous obtenez alors la solution de Dennis, avec dec %eax(1 octet en mode 32 bits). Et oui, les conventions d'appel personnalisées conviennent parfaitement à asm. C'est asm, pas seulement "asm qui est facile à appeler depuis C"; le vrai code écrit en asm utilise des conventions d'appel personnalisées là où cela aide, c'est donc totalement justifiable.
Peter Cordes

1
La convention d'appel normale d'ARM est d'abord arg dans r0laquelle est également le retval, donc Thumb sub r0, #2est de 2 octets.
Peter Cordes

1
Notez qu'aucune de ces fonctions n'est : elles nécessitent un retà la fin du bloc de répétition avant de pouvoir les appeler. Normalement, j'inclus le nombre retd'octets pour mes réponses asm x86. Mais je pense que le fait de plier les règles ici au corps de la fonction est logique, sinon de nombreuses langues ne peuvent pas rivaliser du tout.
Peter Cordes

1
(nvm, cela ne laisse pas le retval dans% al). xchg %eax, %ecx/ sub $4, %al/ xchg %eax, %ecxfait 4 octets et suit la convention _fastcall. L'utilisation des codages courts AL, imm8 et xchg-with-eax est souvent utile pour le golf de code.
Peter Cordes

1
J'utilise habituellement objdump -drwC -Mintelpour obtenir un hexdump des octets de code machine. add r32, imm8est également de 3 octets: opcode + ModR / M + imm8. Toutes les instructions qui peuvent prendre un imm32 ont un opcode alternatif qui prend un imm8 étendu par signe. Voir felixcloutier.com/x86/ADD.html par exemple; toutes les instructions "classiques" ALU (mais pas MOV) qui remontent à 8086 ont tous ces encodages, y compris les AL / AX / EAX spéciaux sans modr / m, juste op + imm8 / 16/32. Cette réponse a des exemples
Peter Cordes

1

Octave: 23 octets

+23;[ans,i]((N==ans)+1)

Si N = L * M, l'expression renvoie 0+i(c'est-à-dire un nombre purement imaginaire), sinon l'expression donne un nombre complexe avec une composante réelle.

Pour un résultat un peu plus agréable au prix d'un octet supplémentaire:

+24;[ans,-1]((N==ans)+1)

Si N = L * M l'expression revient -1, sinon un nombre positif.

Démo:

N=48;
+24;[ans,-1]((N==ans)+1)                                                 #>> 24 
+24;[ans,-1]((N==ans)+1)+24;[ans,-1]((N==ans)+1)                         #>> -1
+24;[ans,-1]((N==ans)+1)+24;[ans,-1]((N==ans)+1)+24;[ans,-1]((N==ans)+1) #>> 23

PS, vous pouvez obtenir le même résultat avec +24;if N==ans;-1;end;ansmais le nombre de bytec est le même


1

Lua, 56 46 octets

a=(a or io.read())-46io.write(a<=0 and a or"")

Génère un 0 (sans retour à la ligne) s'il est égal et rien ou une série de nombres négatifs (avec zéro précédent dans certains cas) s'il n'est pas égal.

Seul: Essayez-le en ligne!

Répété plusieurs fois: essayez-le en ligne!

Explication

a=(a or io.read())-46

Lors de la première itération (quand il an'a pas encore été défini et l'est donc nil), définit aun nombre pris depuis l'entrée, sinon vers lui-même. Dans les deux cas, 46 est ensuite soustrait a.

io.write(a<=0 and a or"")

Cela s'imprime juste asi elle est inférieure à (pour éviter les cas où l'entrée était supérieure à la longueur totale) ou égale à zéro, et la chaîne vide sinon.

-10 octets pour se souvenir que Lua effectue automatiquement les conversions entre les nombres et les chaînes. Oups.


0

JavaScript (ES6), 47 octets

C'est en utilisant la même technique que Benoit Esnard dans cette réponse (à partir de je double la source, tu double la sortie! ).

Imprime 0 si n = 47 * M , ou une valeur non nulle sinon.

n=prompt(setTimeout`alert(n)`)-47/*
n-=47//*///

Démo pour M = 1

n=prompt(setTimeout`alert(n)`)-47/*
n-=47//*///

Démo pour M = 2

n=prompt(setTimeout`alert(n)`)-47/*
n-=47//*///n=prompt(setTimeout`alert(n)`)-47/*
n-=47//*///


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.