Dieu, c'est couvert d'onglets!

26

Utilisateurs d'indentation spatiale, unissez - vous ! Nous devons lutter contre tous les utilisateurs modestes de l'onglet !

Votre mission (si vous choisissez de l'accepter) est d'écrire un programme ou une fonction qui accepte deux arguments:

  • Une chaîne: c'est l'entrée.
  • Un entier positif: il s'agit du nombre d'espaces par tabulation.

Vous devez parcourir chaque ligne de la chaîne et remplacer chaque onglet utilisé pour l'indentation par le nombre d'espaces donné, et chaque onglet non utilisé pour l'indentation (par exemple au milieu d'une ligne) par un espace.

Notez que les lignes telles que \t \tabcsont un comportement indéfini; ils ont été insérés par les utilisateurs maléfiques de l'onglet pour compliquer vos programmes.

Selon la Tabs Must Die Society, votre programme doit être aussi court que possible pour éviter d'être détecté par les mauvais utilisateurs d'onglets.

Exemple

\t est utilisé pour représenter les onglets ici.

Chaîne d'entrée:

a
\t\tb\tc
d

Numéro d'entrée:

4

Sortie:

a
        b c
d

La ligne médiane était en retrait de 8 espaces, 4 par tabulation (puisque le nombre donné était 4).

Chaîne d'entrée:

\ta\t\tb

Numéro d'entrée:

4

Sortie:

    a  b

REMARQUE: ce n'est pas un doublon du défi d'extension d'onglet ; il nécessite un format d'entrée très différent et des exigences légèrement différentes.

kirbyfan64sos
la source
1
Oui , tant que la question ne demande pas explicitement de nombres décimaux (ce qui n'est pas le cas).
Martin Ender
2
doublon possible des onglets Expand (implémentez expand (1))
Ismael Miguel
1
Pouvons-nous supposer que l'entrée ne contient que de l'ASCII imprimable, des tabulations et des retours à la ligne?
Dennis
2
Cas de test proposé: \ta\t\tb, 4(ma version précédente échouait celui - là)
Dennis
2
Nous avons besoin d'une réponse dans l'espace blanc.
Kaz Wolfe

Réponses:

7

CJam, 30 24 23 octets

q{_9=NA=Seasi*' ?@?:N}/

Je refuse généralement de publier du code malveillant sur Internet…

Il s'agit d'un programme complet qui lit la chaîne de STDIN et le nombre comme argument de ligne de commande.

Essayez-le en ligne dans l' interpréteur CJam .

Comment ça marche

q                        Read all input from STDIN.
 {                   }/  For each character C in the input:
  _9=                      Push 1 if C is a tab and 0 otherwise.
     NA=                   See below.
        Seasi*             Push a string of W spaces, where W is the integer from
                           the command-line arguments.
              '            Push a spaces character.
                ?          Select the string if NA= pushed a truthy value, the
                           single space otherwise.
                 @         Rotate C on top of the stack.
                  ?        Select the string of spaces or the single space if _9=
                           pushed 1, the character C otherwise.
                   :N      Save the result in N.

Qu'est NA=- ce que:

  • Pour le premier caractère, Ncontiendra sa valeur par défaut, c'est-à-dire la chaîne "\n".

    Pour tous les caractères suivants, Ncontiendra le résultat de la dernière itération, c'est-à-dire le dernier caractère de l'entrée, un caractère d'espace ou une chaîne d'un ou plusieurs espaces.

  • Si Nest une chaîne, NA=sélectionne l'élément à l'index 10 de N (enroulement). Le résultat sera un espace ou un caractère de saut de ligne. Les deux sont véridiques.

    Si N est un caractère, NA=pousse 1 pour un saut de ligne et 0 sinon.

  • En raison de ce qui précède, NA=poussera une valeur véridique pour le premier caractère, un caractère précédé d'un saut de ligne ou un caractère précédé d'une chaîne d'espaces (retrait qui a déjà été remplacé).

    Dans tous les autres cas (y compris une tabulatrice qui a été remplacé par un espace caractère ), NA=poussera une valeur falsy.

Dennis
la source
6
Heureusement que vous rendez à Internet un service en supprimant les onglets malveillants. ;)
Alex A.
19

K5, 53 45 octets

{{,/(b+a&~b:x*&\a:9=y){$[x;x#" ";y]}'y}[x]'y}

En action:

  {{,/(b+a&~b:x*&\a:9=y){$[x;x#" ";y]}'y}[x]'y}[4;(,"a";"\t\tb\tc";,"d")]
(,"a"
 "        b c"
 ,"d")

Je veux juste que le compte rendu montre que cette question est moralement répréhensible.

JohnE
la source
11
-21346106841 pour... this question is morally reprehensible.
TheNumberOne
3
Cela doit finir par la réponse la plus votée, simplement pour que les gens voient la note de bas de page.
Geobits
Vous pouvez renvoyer le résultat au lieu de l'imprimer sur 3 octets.
kirbyfan64sos
1
@ kirbyfan64sos: J'imprime le résultat pour éviter d'avoir à joindre les lignes. Si je peux accepter et renvoyer le résultat sous forme de liste de chaînes, une pour chaque ligne, je pourrais enregistrer `0:et "" \ n "\`.
JohnE
@JohnE Je n'ai pas mis de règle disant que tu ne peux pas, alors je suppose que tu peux. :)
kirbyfan64sos
8

Perl, 23 octets

Code de 22 octets + ligne de commande de 1 octet

Si tout va bien pas trop effronté pour supposer que l'entrée numérique peut être donnée via le paramètre -i! Assurez-vous de remplacer \ t dans le code ci-dessous par le caractère de tabulation réel.

s/\G\t/$"x$^I/ge;y/\t/ /

Exemple d'utilisation:

printf "a\n\t\tb\tc\nd" | perl -p entry.pl -i4

Ou pour plus de commodité:

printf "a\n\t\tb\tc\nd" | perl -pe 's/\G\t/$"x$^I/ge;y/\t/ /' -i4

Explication:

L'utilisation de l' -pargument exécutera le programme pour chaque ligne de l'entrée, puis affichera le résultat à la fin.

Dans l'exemple ci-dessus, la substitution d'expression régulière remplace \G\tpar " "x4(un espace répété quatre fois). \Gest une construction regex peu connue qui correspond soit à la position de la première correspondance si la première itération, soit à partir de la position de la correspondance précédente sinon la première itération, ce qui signifie qu'elle ne remplacera que tous les onglets au début de la chaîne, et faites-le un par un. Le y/\t/ /remplace simplement tous les onglets restants par des espaces.

Jarmex
la source
2

Julia, 69 59 octets

f(s,n)=(r=replace)(r(s,r"^\t*"m,i->" "^endof(i)n),"\t"," ")

Non golfé:

function f(s::String, n::Int)
    # Replace the leading indentation tabs
    r1 = replace(s, r"^\t*"m, i -> " "^endof(i)n)

    # Replace any remaining tabs between words
    r2 = replace(r1, r"\t", " ")

    # Return
    r2
end

Enregistrement de 10 octets et correction d'un problème grâce à Glen O!

Alex A.
la source
Y a-t-il un avantage à remplacer les onglets d'indentation principaux séparément? Il me semble qu'il devrait être géré directement par la partie "onglets restants". De plus, votre partie "remplacer les onglets entre le texte" ne correspondra qu'à un seul onglet, et si vous en avez "hello\t\t1"?
Glen O
Si nous supposons que toute l'indentation se fait avec des onglets (pas de "\t \t"situations), vous pouvez le faire:, f(s,n)=(r=replace)(r(s,r"^\t*"m,i->" "^endof(i)n),"\t"," ")qui utilise une fonction de remplacement et interceptera tous les onglets d'indentation en une seule fois.
Glen O
@GlenO Wow, c'est vraiment du génie. Merci beaucoup!
Alex A.
J'ai remarqué que ma réponse avait été rejetée. Y a-t-il quelque chose que j'ai fait de mal? Je serais ravi de résoudre tout problème.
Alex A.
Je ne vois aucun problème. Peut-être que c'est juste un de ces types vindicatifs qui dévalorisent parce qu'ils n'aiment pas une langue, ou des choses comme ça? Je ne vois aucun défaut.
Glen O
2

Haskell, 82 octets

n!('\t':x)=([1..n]>>" ")++n!x
n!x=f<$>x
f '\t'=' '
f x=x
g n=unlines.map(n!).lines

Alors g 3 "a\n\t\tb\tc\nd"fait la chose.

Lynn
la source
2

Mathematica, 42 37 octets

Merci à @ LegionMammal978 pour plusieurs suggestions de sauvegarde de code. Le premier paramètre, #est pour le texte d'entrée, le deuxième paramètre,, #2pour le nombre d'espaces par tabulation.

StringReplace[#,"\t"->" "~Table~{#2}]&
DavidC
la source
En outre, vous pouvez changer Table[" ",{#2}]pour " "~Table~{#2}enregistrer un octet. Pourquoi y insérez-vous StringJoinla chaîne vide?
LegionMammal978
1

Ruby 49 octets

def r s,t;s.gsub! /^\t/,' '*t;s.gsub!"\t",' ';end
MegaTom
la source
2
Cela ne fonctionne pas s'il y a deux onglets au début d'une ligne.
Pas que Charles
1

JavaScript (ES6), 70

En utilisant des chaînes de modèle, la nouvelle ligne est significative et comptée

(s,n,r=n)=>[...s].map(c=>c<`
`?` `.repeat(r):(r=c<` `?n:1,c)).join``

Testez l'exécution de l'extrait ci-dessous dans Firefox.

F=(s,n,r=n)=>[...s].map(c=>c<`
`?` `.repeat(r):(r=c<` `?n:1,c)).join``

// TEST
out=x=>O.innerHTML+=x+'\n\n'

out('Input: "A\\n\\t\\tB\\tC\\nD" 4\nOutput:\n'+F('A\n\t\tB\tC\nD',4))

out('Input: "\\tA\\t\\tB" 4\nOutput:\n'+F('\tA\t\tB', 4))
<pre id=O></pre>

edc65
la source
1
Wow un downvote! Peut-être quelqu'un qui ne peut pas lire ou comprendre «Tester dans Firefox»?
edc65
Je soupçonne un préjugé linguistique. Julia et CJam ont également obtenu des votes négatifs.
Dennis
1

CoffeeScript, 72 octets

(s,n)->s.replace(/^\t+/mg,(m)->" ".repeat(m.length*n)).replace /\t/g," "

(Essayer de jouer au golf au moins 2 bouchées supplémentaires, donc il battra la solution ES6 ... Aide appréciée: D)

Usage:

f=(s,n)->s.replace(/^\t+/mg,(m)->" ".repeat(m.length*n)).replace /\t/g," "
str="""
My nice\tString
\tIndent <--
\t\tDouble
""" #\t is recognized as tab by CS
alert(f(str,4))
Bojidar Marinov
la source
1

Rétine, 42 octets

Toutes les occurrences de .sont des espaces, toutes \tsont des tabulations littérales (1 octet) et<empty> représentent un fichier vierge. C'est juste pour la lisibilité. Je ne suis pas non plus entièrement sûr de faire correctement la boucle, mais je pense que oui. Chaque ligne doit être placée dans son propre fichier. J'ai ajouté 1 octet pour chaque fichier supplémentaire.

L'entrée est supposée être en Unary sur sa propre ligne à la fin de l'entrée.

(1*)$
_$1
m+`(?<!^|\t)\t
.
(`1$
<empty>
)`\t
\t.
\t|_
<empty>

Explication

J'ajoute un _avant l'entrée Unary pour le délimiter lors du remplacement, de sorte que je ne supprime pas les derniers de la chaîne d'entrée. Ensuite, je remplace tous les onglets qui ne se trouvent pas au début d'une ligne par un seul espace. Ensuite, je boucle, en supprimant un seul 1et en ajoutant un seul espace après chaque onglet, jusqu'à ce que je manque de saisie. Enfin, je nettoie en supprimant les onglets et le trait de soulignement.

mbomb007
la source
1

Python, 72 68 octets

Les tabulations sont des tabulations littérales (1 octet), elles r'...'ne sont donc pas nécessaires. Malheureusement, Python nécessite des analyses / anticipations "à largeur fixe", donc je ne peux pas l'utiliser (?<!^|\t). Utilise à peu près la même méthode que ma solution Retina.

import re
lambda s,n:re.sub('\t',' '*n,re.sub('(?<!^)(?<!\t)\t',' ',s))
mbomb007
la source
1

Stax , 20 octets

ÜR╧█╧╫≡eX,)~σOÜ¢G╩N‼

Exécuter et déboguer

Ce programme lit la première ligne comme largeur de retrait et le reste de l'entrée comme programme.

récursif
la source
0

Haskell , 75 octets

s#m|let('\t':r)#n=(' '<$[1..n])++r#n;(x:r)#n=x:r#(m^sum[1|x<' ']);e#_=e=s#m

Essayez-le en ligne! Cela suppose que l'entrée ne contient que des caractères imprimables ainsi que des tabulations et des sauts de ligne, comme le permet OP dans les commentaires.

Explication:

La #fonction externe prend une chaîne set un nombre met appelle la fonction interne définie localement #avec les mêmes arguments. Ceci est fait pour garder une trace de la mvaleur d' origine , car la #fonction interne change le nombre:

  • ('\t':r)#n=(' '<$[1..n])++r#nSi vous rencontrez un onglet, remplacez-le par des nespaces et laissez ninchangé.
  • (x:r)#n=x:r#(m^sum[1|x<' '])Si une partie xqui n'est pas un onglet est rencontrée, conservez-la telle quelle, mais définissez-la nsur le numéro d'origine ms'il xs'agit d'une nouvelle ligne et dans le 1cas contraire. Cela se fait par m^sum[1|x<' ']: mest porté à la puissance sum[1|x<' ']dont évalue 1quand xest plus petit qu'un espace (c'est-à-dire une nouvelle ligne), donc nous obtenons m^1 = m. Sinon c'est 0et nous avons m^0 = 1.
Laikoni
la source
0

Java 11, 134 octets

n->s->{var r="";for(var p:s.split("\n")){for(;p.charAt(0)==9;p=p.substring(1))r+=" ".repeat(n);r+=p+"\n";}return r.replace('\t',' ');}

Essayez-le en ligne.
REMARQUE: Java 11 n'est pas encore sur TIO, il " ".repeat(n)a donc été émulé comme à la repeat(" ",n)place (avec le même nombre d'octets).

Explication:

n->s->{                 // Method with integer & String parameters and String return-type
  var r="";             //  Result-String, starting empty
  for(var p:s.split("\n")){
                        //  Loop over the rows (split by new-lines)
    for(;p.charAt(0)==9;//   Inner loop as long as the current row starts with a tab
       p=p.substring(1))//     After every iteration: remove the first character (tab)
      r+=" ".repeat(n); //    Append `n` amount of spaces to the result-String
    r+=p+"\n";}         //   Append the rest of the row with a newline to the result
  return r.replace('\t',' ');} 
                        //   Replace any remaining tabs with a space, and return the result
Kevin Cruijssen
la source