Texte aligné à droite

27

Votre travail consiste à prendre une entrée de chaîne et un nombre et à aligner la chaîne à droite, en faisant de la largeur du texte le nombre. Quand une ligne est trop longue, cassez-la et mettez le reste sur la ligne suivante, en répétant jusqu'à ce que ce ne soit pas nécessaire. Si une ligne est plus courte que la largeur, remplissez-la avec des espaces. Plusieurs sauts de ligne peuvent se produire et doivent être traités comme tout autre caractère unique.

Par exemple, la chaîne

Programming
Puzzles
&
Code
Golf

et le nombre 5produirait:

Progr
ammin
    g
Puzzl
   es
    &
 Code
 Golf

Alors que la même chaîne et le même nombre 10produiraient:

Programmin
         g
   Puzzles
         &
      Code
      Golf

La chaîne

a

b

et le chiffre 5 produirait:

    a
      <-- note the 5 spaces
    b

Le code le plus court gagne!

Trébuchette
la source
1
Le texte dit «Brisez les lignes lorsque cela est nécessaire [...]», mais vos exemples suggèrent que vous coupez après chaque mot, même quand il conviendrait. Veuillez clarifier: plaçons-nous chaque mot sur une nouvelle ligne ou implémentons-nous un algorithme de retour à la ligne réel?
Timwi
Peut-il y avoir des espaces au milieu d'une ligne d'entrée, par exemple Programming Puzzles\n&\nCode Golf?
Sp3000
@ sp3000 Il peut y avoir n'importe quel caractère, y compris les espaces.
Trebuchette
@Timwi: L'exemple a un mot par ligne. Il aurait été préférable d'inclure quelques lignes de plusieurs mots pour indiquer clairement que l'espace dans une ligne n'est pas spécial. (c'est-à-dire qu'il n'y a que des nouvelles lignes et des non-nouvelles lignes.)
Peter Cordes

Réponses:

10

Python 2, 84

s,n=input()
for w in s.split('\n'):
 w=w or' '
 while w:print w[:n].rjust(n);w=w[n:]

Prend en entrée une chaîne avec des sauts de ligne et un nombre, et imprime le résultat. Pour chaque ligne de l'entrée, prend et imprime les ncaractères à la fois, en utilisant la fonction intégrée rjustpour remplir la gauche avec des espaces avant l'impression.

J'ai corrigé le cas de ligne vide avec le hack w=w or' '. Il y a probablement une meilleure méthode mais je ne vais pas y penser beaucoup.

xnor
la source
8

CJam, 21 octets

li_qN/Sfe|f/ff{\Se[N}

Merci à @ Sp3000 pour avoir joué 1 octet et ouvert la voie à 3 autres.

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

Comment ça marche

li                     Read an integer L from the first line of input.
  _                    Push a copy.
   qN/                 Split the remaining input at linefeeds.
      Sfe|             Map `OR " "'; the replaces empty lines with a space.
          f/           Split each line into chunks of length L.
            ff{     }  For each chunk, push L and the chunk; then:
               \         Swap L with the chunk.
                Se[      Left-pad the chunk to length L by prepending " ".
                   N     Push a linefeed.
Dennis
la source
5

Pyth, 16

jm>Q+*\ QdscRQ.z

Essayez-le en ligne ici

Explication

jm>Q+*\ QdscRQ.z             : Q is the number on the first line, .z takes the rest
           cRQ.z             : chop each line of .z into chunks of Q characters
 m        s                  : remove nested lists and map over the result
    +*\ Qd                   : add Q spaces to each line d
  >Q                         : take the last Q characters of that result
j                            : join results on newlines
FryAmTheEggman
la source
4

Perl, 39 octets

perl -ni5 -e 's!^$|.{1,$^I}!printf"%${^I}s
",$&!ge'

36 octets + 3 octets pour -ni. La largeur d'habillage est passée comme argument à -i.

Gère correctement les lignes vides en les remplissant d'espaces:

$ echo -e "Programming\nPuzzles\n\n&\n\nCode\nGolf" | perl -ni5 -e 's!^$|.{1,$^I}!printf"%${^I}s
",$&!ge'
Progr
ammin
    g
Puzzl
   es

    &

 Code
 Golf

Comment ça marche

Cette solution utilise l'opérateur de substitution pour parcourir l'entrée, économisant ainsi un octet sur la forboucle équivalente . Le vrai truc, cependant, est dans l'expression régulière sur le LHS de la substitution:

^$|.{1,$^I}

Avec le modificateur global, cela correspondra aux $^Icaractères à la fois; lorsqu'il reste moins de $^Icaractères dans la chaîne, tout correspondra jusqu'à la fin. L'alternance avec ^$est nécessaire pour gérer les lignes vierges. Par exemple:

$ echo -e "foo\n\nbar" | perl -ni2 -E 'say "<$_>" for /^$|.{1,$^I}/g'
<fo>
<o>
<>
<ba>
<r>

Le RHS de la substitution utilise simplement printfpour remplir à gauche le morceau correspondant avec des espaces.

ThisSuitIsBlackNot
la source
J'oublie toujours $^I!
Dom Hastings
@DomHastings J'ai appris cette astuce de chilemagic, qui l'a mentionné dans un commentaire sur un autre défi .
ThisSuitIsBlackNot
3

Javascript (ES6), 107

Je souhaite que JS ait une fonction pad intégrée. Tant pis.

(a,b)=>a.replace(eval(`/(.{${b}})(?!\\n)/g`),`$1
`).split`
`.map(c=>(Array(b).join` `+c).slice(-b)).join`
`

Explication:

(a, b)=>

  // searches for sequences of characters longer than b without a newline after them and
  // adds a newline after every b characters of the sequence
  a.replace(eval(`/(.{${b}})(?!\\n)/g`), '$1\n')
    .split('\n')
    .map(c=>

      // prepends b spaces to each string then slices it from the right down to length b
      ( Array(b).join(' ') + c ).slice(-b)

    ).join('\n')
DankMemes
la source
3

Julia, 126 octets

f(s,n)=for i=split(s,"\n") while length(i)>0 println(lpad(i[1:min(n,end)],n));length(i)<n?break:(i=i[min(n+1,end):end])end;end

Non golfé:

function f(s::String, n::Int)
    for i in split(s, "\n")
        while length(i) > 0
            println(lpad(i[1:min(n,end)], n))
            length(i) < n ? break : (i = i[min(n+1,end):end])
        end
    end
end
Alex A.
la source
2

Bash, 62 , 61 + fonctionnalité, 59

Plus court s'il Npeut être défini par l'appelant, au lieu d'avoir à le lire comme première ligne d'entrée.

# width as a function arg: 59 chars
f()while read -rn$1 r;do [[ $r ]]&&printf %$1s\\n "$r";done
# width on stdin: 64 chars  (not updated with later suggestions&ideas)
read N;while read -rn$N r;do [[ $r ]]&&printf %$N's\n' "$r";done

Cela ne parvient pas à gérer les lignes vides dans l'entrée. Sinon, cela ne soumet pas les données d'entrée à la séparation des mots, à l'expansion du nom de chemin ou ne les traite pas comme plus que des données brutes.

read -n$Nenregistre un personnage, mais laisse readMunge \.

Le [[ $r ]]&&est nécessaire car read -n4ne peut pas regarder en avant pour voir que le prochain caractère est une nouvelle ligne. Il définit rdonc une chaîne de 4 caractères et la lecture suivante produit une chaîne vide de zéro caractère. Filtrer ces fausses nouvelles sans filtrer les vraies nouvelles lignes nécessiterait un état de suivi: que la ligne précédente ait ou non une longueur maximale. Il faudrait plus de code ou une approche totalement différente.

[[ $r ]]est plus court que [ -n "$r" ]ce qui est nécessaire pour éviter les erreurs si la ligne commence par -z foo, ou est *ou quelque chose, si vous l'avez utilisé [ $r ].

La justification se produit avec la chaîne de format standard printf "% 4s".

Testez avec

f()(while read -rn$1 r;do [[ $r ]]&&printf %$1s\\n "$r";done); (echo 4; echo -e "*\n\\"; cat /tmp/lines) | f 4
Peter Cordes
la source
1. J'inclurais -rle nombre d'octets. 2. f()(while ... done)est un peu plus court.
Dennis
@Dennis: Sans [[ $r ]]&&, si N = 4, une ligne d'entrée de longueur 4 produira une ligne de sortie vierge là où il n'y en avait pas auparavant. Parce que readrenvoie une chaîne de 4 caractères, puis voit une nouvelle ligne lors du prochain appel et revient immédiatement. Merci aussi pour l' ()astuce. Je ne savais pas que vous pouviez définir les fns de cette façon.
Peter Cordes
Je recommande de lire des conseils pour jouer au golf à Bash . C'est une excellente ressource.
Dennis
En fait, comme whilec'est déjà composé, vous n'avez même pas besoin des parenthèses:f()while ... done
Dennis
@ Dennis: wow, haxx. Merci pour le lien. Quelques-unes de ces choses étaient nouvelles pour moi, et j'ai corrigé deux ou trois choses dans une autre réponse :) Je ne joue pas au golf normalement, mais> 15 ans d'expérience en tant que junkie en ligne de commande m'ont appris une chose ou deux :)
Peter Cordes
2

Haskell, 108 octets

import Data.List.Split
k[]=[""]
k x=x
f n=unlines.(map(\l->([1..n-length l]>>" ")++l).k.chunksOf n=<<).lines

Exemple d'utilisation:

*Main> putStr $ f 5 "a\n\nb\ncd\nMatamorphosis"
    a

    b
   cd
Matam
orpho
  sis

Comment ça marche

                              .lines   -- split input string at newlines
                           =<<         -- for every line
                  chunksOf n           --    split into chunks of length n
                k                      --    fix empty lines
    map                                --    for every chunk
        \l->([1..n-length l]>>" "      --      make a string of missing spaces
                        ++l            --      and append the chunk
unlines                                -- join padded chunks with newlines in-between
nimi
la source
1

GNU awk + bash, 70

f()(awk -vFPAT=.\{,$1} '{for(i=0;i++<NF;){printf "%'$1's\n",$i}}/^$/')

L'utilisation de bash pour insérer le compte dans le programme awk est problématique. plus petit que le lire avec un NR==1{N=$0}bloc.

Lisez une ligne à la fois. Divisez-vous en 4 caractères au maximum, en utilisant FPAT. (correspond aux champs, plutôt qu'aux séparateurs. Extension GNU.) printf chaque champ séparément. (ORS par défaut = \ n).

La /^$/règle est là pour imprimer des lignes vides, qui ont NF = 0 et donc ne s'impriment pas du tout dans l'autre bloc. Contrairement à ma solution pure-bash, cela fonctionne en fait dans le cas général.

Semi-indépendant, mais mon idée jusqu'à présent pour Perl est de 112 caractères pour juste le code Perl:

(echo 4; echo -e 'foo\nbar'; echo -e "*\n\\"; echo '~$(true)'; cat /tmp/lines) |  # test input
perl -e '$N=<>;$/=\1;print "$N\n"; while(<>){if(/\n/ or length($l)>=$N){printf("%$4s\n",$l);$l=/\n/?"":$_;}else{$l.=$_;}}'

Cela mange l'une des nouvelles lignes et est beaucoup trop long. $/=\1lit un octet à la fois. Nous ajoutons à $ l. Une approche ligne par ligne avec une approche de largeur fixe serait probablement plus courte.

Peter Cordes
la source
1

Utilitaires Bash + GNU, 41

fold -$1|sed ":;s/^.\{,$[$1-1]\}\$/ &/;t"

La chaîne est entrée via STDIN, la largeur est entrée par la ligne de commande arg:

ubuntu@ubuntu:~$ echo 'Programming
Puzzles
&
Code
Golf'|./ralign.sh 10
Programmin
         g
   Puzzles
         &
      Code
      Golf
ubuntu@ubuntu:~$
Traumatisme numérique
la source
1

Python 2, 151 octets

s,n=input();N='\n'
for w in[i.lstrip()if i.replace(' ','').isalpha()else i for i in s.replace(N,'\n ').split(N)]:
 while w:print w[:n].rjust(n);w=w[n:]

Il s'agit d'une adaptation de la réponse de @ xnor ci-dessus, car la sienne ne gère pas correctement les nouvelles lignes.


La forboucle a été modifiée de:

for w in s.split('\n'):

à:

for w in[i.lstrip()if i.replace(' ','').isalpha()else i for i in s.replace(N,'\n ').split(N)]:

Exemple

$ python main.py
"Programming\n\n\nPuzzles\n\n&\n\nCode\nGolf", 5
Progr
ammin
    g


Puzzl
   es

    &

 Code
 Golf
Zach Gates
la source
1

C #, 143 octets

(s,n)=>Join("\n",s.Split('\n').SelectMany(l=>(l.Any()?l:" ").Select((c,i)=>new{c,i}).GroupBy(o=>o.i/n,o=>o.c).Select(g=>Concat(g).PadLeft(n))))

Linq vous permet de faire des expressions assez noueuses. GroupByest utile ici, mais c'est dommage qu'ils n'aient pas pu créer de surcharge de fonction en prenant l'index.

Attribuer le lambda à un Func<string, int, string>pour l'exécuter

Moins golfé:

Func<string, int, string> Align = (s, n) => Join("\n", 
    s.Split('\n')
     .SelectMany(l => (l.Any() ? l : " ")
         .Select((c, i) => new { c, i })
         .GroupBy(o => o.i / n, o => o.c)
         .Select(g => Concat(g).PadLeft(n))));
Carl Walsh
la source
1

Groovy, 63 octets

Renvoie la chaîne correctement allouée. Je ne savais pas qu'il y avait jusqu'à présent une fonction padLeft (et padRight, padCenter).

f={s,n->s.split("(?<=\\G.{$n})|\n")*.padLeft(n," ").join("\n")}
dbramwell
la source
1

Javascript 174 136

function R(s,x){return s.replace(new RegExp(".{"+x+"}","g"),"$&\n").replace(/[^\n]*/g,function(m){
while(m.length<x)m=" "+m;return m;})}
marteau-de-loup
la source
1

Ceylan, 107

String w(String s,Integer n)=>"\n".join{for(l in s.lines)for(p in l.partition(n))String(p).padLeading(n)};
Roland Tepp
la source
1

Matlab, 99 octets

Merci à @beaker pour avoir supprimé 6 octets!

Utilisation et fonction anonyme:

@(s,k)fliplr(char(cellfun(@fliplr,strsplit(regexprep(s,sprintf('\\S{%i}',k),'$0\n'),'\n'),'un',0))) 

Définissez la fonction et utilisez-la anspour l'appeler:

>> @(s,k)fliplr(char(cellfun(@fliplr,strsplit(regexprep(s,sprintf('\\S{%i}',k),'$0\n'),'\n'),'un',0)))

ans =

@(s,k)fliplr(char(cellfun(@fliplr,strsplit(regexprep(s,sprintf('\\S{%i}',k),'$0\n'),'\n'),'un',0)))

>> ans(['Programming' 10 'Puzzles' 10 '&' 10 'Code' 10 'Golf'], 5) %% 10 is line feed

ans =

Progr
ammin
    g
Puzzl
   es
    &
 Code
 Golf
Luis Mendo
la source
1

Burlesque, 28 octets

Identique à la version ci-dessous, mais traite la ligne 1 comme le nombre et les autres lignes comme la chaîne.

lng_riPpun{pPco{pP' lp}mu}Wl

Utilisation comme dans:

$ cat input.txt | blsq --stdin "lng_riPpun{pPco{pP' lp}mu}Wl"
Progr
ammin
    g
Puzzl
   es
    &
 Code
 Golf

Ancienne version (16 octets):

{5co{5' lp}mu}Wl

Exemple:

blsq ) "Programming\nPuzzles\n&\nCode\nGolf"{5co{5' lp}mu}Wl
Progr
ammin
    g
Puzzl
   es
    &
 Code
 Golf
mroman
la source