Créez une contre-chaîne illimitée

11

Une contre - chaîne est une sorte de données de test auto-descriptives utilisées dans les tests de logiciels. Je ne suis pas sûr qu'il ait été inventé par James Bach , mais je le sais de là.

L'idée est la suivante: les données de test contiennent de nombreux astérisques ( *). Le nombre devant l'astérisque vous indique la durée des données de test à ce stade. Si vous avez besoin de connaître une position dans les données de test qui n'est pas un astérisque, recherchez le dernier astérisque, regardez le numéro avant et ajoutez le nombre de chiffres qui suivent.

La séquence commence comme ceci:

2*4*6*8*11*14*17*20*23*
             ^

Comme vous pouvez le voir, l'astérisque marqué est en position 14.

Si un fichier se trouve tronqué comme suit

[...]2045*20

vous pouvez alors déduire qu'il y a une limite de 2047 caractères quelque part (2045 où l'astérisque est plus 2 pour 2et 0).

C'est votre tâche de créer le programme le plus court (c'est le ) qui génère (std :: out ou fichier ou autre) une longue chaîne de test arbitraire de ce format. La longueur en caractères est donnée en argument. Le programme doit prendre en charge jusqu'à 2 Go de données de test (valeur d'entrée 2147483647 caractères).

Positions "dangereuses" dans le fichier de 2 Go:

8*11*
98*102*
998*1003*
9998*10004*
99998*100005*
999995*1000003*
9999995*10000004*
99999995*100000005*
999999995*1000000006*

Cela devrait répondre à la question de @Leaky Nun s'il y a une décision à prendre entre 995 * 999 * et 995 * 1000 * ou similaire: non.

La fin du fichier de 2 Go avec la valeur d'entrée 2147483647 est:

2147483640*2147483
Thomas Weller
la source
S'il ne s'arrête pas, comment le testez-vous?
Leaky Nun
2
Cette longueur est-elle en caractères?
TheBikingViking
4
Pouvez-vous prouver que nous n'aurions jamais à choisir entre 995*999*et 995*1000*ou quelque chose comme ça?
Leaky Nun
1
À l'avenir, veuillez utiliser le bac à sable pour résoudre vos problèmes avant de les publier.
Mego
1
@ThomasWeller Si nous pouvons créer une sortie plus longue, pouvons-nous prendre aucune entrée et produire simplement la chaîne de 2 Go?
xnor

Réponses:

4

Haskell, 60 58 octets

En fonction, nous obtenons:

f=length.show
iterate(\n->1+n+(f$n+1+f n))2>>=(++"*").show

Programme complet, 72 70 octets

Cela génère une contre-chaîne infinie vers STDOUT:

f=length.show
main=putStr$iterate(\n->1+n+(f$n+1+f n))2>>=(++"*").show

La saisie de la longueur nécessite 20 octets supplémentaires:

main=interact(\j->take(read j)$iterate(\n->1+n+(f$n+1+f n))2>>=(++"*").show)

Cela fonctionne jusqu'à votre taille approximative de RAM, car Haskell utilise par défaut les types intégraux numériques Integer.

ThreeFx
la source
3

Pyth, 25 17 15 14 octets

<uu++GlN\*k)Qk

Essayez-le en ligne.

La longueur est prise via STDIN.

PurkkaKoodari
la source
2

Python 2, 74 72 66 64 61 octets

f=lambda n,i=2:"%d*"%i+f(n,len(`i+2`)-~i)[:n-2]if i<n*2else""

Prend un entier n et génère une contre-chaîne de longueur n.

version du programme, 69 octets:

s,n,i="",input(),2
while i<2*n:s+="%d*"%i;i+=len(`i+2`)+1
print s[:n]

Prend un entier n de stdin et imprime une contre-chaîne de longueur n.

Version alternative plus courte, mais presque fonctionnelle:

n,i=input(),2
while i<2*n:print("%d*"%i)[:n-i],;i+=len(str(i+2))+1
KarlKastor
la source
1

PowerShell v5, 97 octets

param($n)$l=1;for($i=0;$i-lt$n){$i+="$i*".length;if("$i".Length-gt$l){$i++;$l++};ac .\o "$i*" -n}

Prend l'entrée comme argument de ligne de commande $n, définit l'aide $lque nous utilisons pour garder une trace de notre longueur entière. Ensuite, nous bouclons 0jusqu'à $n. Chaque itération, on incrémente $ipar la .lengthde la chaîne formée à partir $iet un astérisque. Ensuite, si le .lengthde $ichange (par exemple, nous sommes passés de 2 chiffres à 3 chiffres), nous incrémentons à la fois la $lvariable helth ength et $i(pour tenir compte du chiffre supplémentaire). Nous utilisons ensuite la add-contentcommande pour ajouter "$i*"au fichier .\odans le répertoire courant, avec -noNewLine.

NB

  • Nécessite la v5, car le -noNewLineparamètre a finalement été ajouté dans cette version.
  • PowerShell convertira automatiquement de [int]à [double](non, je ne sais pas pourquoi il ne va pas [long]), donc cela traitera correctement les entrées jusqu'à et plus que 2147483648, sans problème. Théoriquement, il gérera les entrées quelque part jusqu'à environ 1.79769313486232E+308(valeur maximale de [double]) avant de se plaindre, mais je m'attends à ce que le disque se remplisse avant que cela ne se produise. ;-)
  • En raison de la vérification conditionnelle de la boucle, cela produira dans le fichier un minimum de la longueur d'entrée. Par exemple, pour l'entrée, 10cela produira 2*4*6*8*11*, car 11la première $ivaleur est supérieure à l'entrée.

PowerShell v2 +, également 97 octets (non concurrents)

param($n)$l=1;-join(&{for($i=0;$i-lt$n){$i+="$i*".length;if("$i".Length-gt$l){$i++;$l++};"$i*"}})

Au lieu d’envoyer vers un fichier, cela encapsule les itérations de boucle, puis -joinles rassemble dans une chaîne. Cela lui permet de fonctionner pour les versions antérieures à la v5. Cependant, puisque .NET définit un [string]avec un constructeur comme String(char c,Int32 length), cette version ne satisfait pas l'exigence d'entrée maximale, car la chaîne de sortie va déborder et barf.

En outre, vous ne souhaiterez peut-être pas avoir une chaîne de ~ 2 Go flottant dans votre pipeline. Je dis juste.

AdmBorkBork
la source
1.79769313486232E + 308 ne fonctionnera certainement pas, car l'ajout de petits nombres à un flottant ne changera plus la valeur. Voir stackoverflow.com/questions/12596695/… Donc, je suppose que cela cesse de fonctionner une fois qu'il a été "mis à niveau" pour doubler
Thomas Weller
@ThomasWeller PowerShell [double]s est 64 bits. Par exemple, lancez for($i=2147483645;$i-lt2147483655;$i++){"$i - " + $i.GetType()}affiche une progression constante de $imais les Typechangements à 2147483648la double. Je suis sûr qu'à un moment donné, cela cessera de fonctionner, probablement autour de ~ 15 chiffres de précision ou lorsque le .ToStringcommence à utiliser e. Le [double]::MaxValueétait plus d'une blague que une limite jetable grave supérieure.
AdmBorkBork
1

Python 3, 126 114 99 octets

def f(x,s=''):
 i=t=2
 while len(s)<x:i+=len(str(t+i))-len(str(t));s+=str(t)+'*';t+=i
 print(s[:x])

Une fonction qui prend l'entrée via l'argument du nombre de caractères auquel tronquer la chaîne et imprime dans STDOUT.

Comment ça fonctionne

La différence entre les nombres de la chaîne est initialement de 2. Chaque fois qu'un ordre de grandeur est passé, cette différence est augmentée de 1; ceci peut être réalisé en prenant la différence entre le nombre de chiffres du numéro actuel et le nombre de chiffres du numéro actuel ajouté à la différence, qui est 1 uniquement lorsque cela est nécessaire. La fonction boucle simplement pendant que la longueur de la chaîne est inférieure à l'entrée, ajoute à la chaîne et met à jour la différence et le nombre selon les besoins, puis tronque avant l'impression.

Essayez-le sur Ideone

Version de sortie infinie, 69 octets

s=i=2
while 1:i+=len(str(s+i))-len(str(s));print(end=str(s)+'*');s+=i
TheBikingViking
la source
1

R, 92 octets

    N=nchar;f=function(n){z=0;y="";while(z<n){z=z+N(z+N(z)+1)+1;y=paste0(y,z,"*")};strtrim(y,n)}

Exemple de sortie:

f (103) [1] "2 * 4 * 6 * 8 * 11 * 14 * 17 * 20 * 23 * 26 * 29 * 32 * 35 * 38 * 41 * 44 * 47 * 50 * 53 * 56 * 59 * 62 * 65 * 68 * 71 * 74 * 77 * 80 * 83 * 86 * 89 * 92 * 95 * 98 * 102 * 1 "

JDL
la source
0

Gelée , 22 19 18 octets

2µṾL+®‘¹©=¡=µ³#j”*

Essayez-le en ligne!

Trouvez les premiers nnombres de la chaîne, puis rejoignez la liste avec un astérisque. Ce sera toujours plus long que nce qui a été autorisé par OP dans les commentaires.

Le programme met à jour sélectivement le registre avec le numéro actuel dans la séquence de la #boucle avec ¹©=¡. J'espérais que cela pourrait être plus court, en mettant ©après le deuxième µpar exemple, mais malheureusement cela ne fonctionne pas et je n'ai rien compris de plus court.

dylnan
la source