36
\$\begingroup\$

Twisting Words!

Given a string and a positive integer. You must twist the string, back and forth.

Example Input / Output

Input

Programming Puzzles & Code Golf
4

Output

Prog
mmar
ing 
zzuP
les 
oC &
de G
 flo

Input

The input can be taken in through STDIN, or function argument. The input will consist of a string and a positive integer, n. The integer will determine the length of each twisted line.

The string is twisted back-and-forth. An input of HELLO, WORLD! and 5 would look like:

HELLO, WORLD!

Output

The output will be the twisted text. It may not any trailing whitespace. If the input string length is not divisible be the line length, add a space until the line is filled:

An example of this:

Input

Hello, World!
5

Output (Note the whitespace at the very end)

Hello
roW ,
ld!  
\$\endgroup\$
4
  • \$\begingroup\$ Related: a readable implementation at CodeReview \$\endgroup\$ – Caridorc Aug 23 '15 at 20:59
  • 4
    \$\begingroup\$ It may not any trailing whitespace. Golfed away a verb? \$\endgroup\$ – Adám May 13 '18 at 21:19
  • 1
    \$\begingroup\$ May we return a list of lines? \$\endgroup\$ – Adám May 13 '18 at 21:19
  • \$\begingroup\$ While working on this, I was wondering if this was made a bit more challenging. In addition to twisting the words, we should also find patterns that match between two lines. For example, if the word was This pearl was made from the peas and we broke it by 4 chars, then aep will appear on line 2 and line 8. We need to identify the matches. If there are more than one match, then we need to print all the matches including line number that matched :) \$\endgroup\$ – Joe Ferndz Sep 2 '20 at 5:51

44 Answers 44

1
2
1
\$\begingroup\$

Bash, 83 74

for((i=0;i<${#1};i+=$2));do b=cat;((i/$2%2))&&b=rev;echo ${1:i:$2}|$b;done

This alternates between cat and rev for substrings of the first argument with a length of the second argument.

Special variables used include

  • ${#1} (the length of the string $1)
  • ((i/$2%2)) (an arithmetic expression dividing incrementor $i by $2 and then taking its modulo to determine odd vs even, which dictated whether or not to use rev)
  • ${1:i:$2} (substring of $1 starting at position $i with a length of $2).
\$\endgroup\$
1
  • \$\begingroup\$ Hm, I did this independent of the other bash answer, which I only just saw now. We have effectively the same logic. ... actually, viktorahlström's answer just let me shave off another 9 characters. \$\endgroup\$ – Adam Katz Aug 22 '15 at 21:51
1
\$\begingroup\$

JavaScript ES6, 113 bytes

Just my own crack at my own question. It will add spaces so it is divisible by n, that way it's simply splitting and reversing.

(s,n)=>(s+' '.repeat(n-s.length%n)).match(eval(`/.{1,${n}}/g`)).map((l,i)=>i%2?[...l].reverse().join``:l).join`
`
\$\endgroup\$
1
\$\begingroup\$

Shell/Bash, 135 bytes

s=0;while true;do ((s%($2*2)))&&{ echo "${1:s:$2}"|rev;s=$((s+$2)); }||{ echo "${1:s:$2}";s=$((s+$2)); };((s>=${#1}))&&{ exit 1; };done
\$\endgroup\$
2
  • \$\begingroup\$ Would it be possible to replace the true with either 1 or 1=1? \$\endgroup\$ – Taylor Scott May 19 '18 at 22:51
  • \$\begingroup\$ Yes, you can do while :. I didn't see this answer when I composed my answer, but it has very similar logic, and I borrowed the more concise arithmetic evaluation to reduce my version from 83 bytes to 74. \$\endgroup\$ – Adam Katz Aug 24 '18 at 18:51
1
\$\begingroup\$

Python 2, 86 bytes

Here's my answer (borrowing some input processing from @mbomb007). Unfortunately can't define the len(s) as a variable as the length of the string changes after padding with spaces. Now also using rjust() instead of ljust() as @AlexN suggested.

s,n=input()
k=n
while k<=len(s):print s[k-n:k]+'\n'+s[k+n-1:k-1:-1].rjust(n);k+=2*n  
\$\endgroup\$
1
\$\begingroup\$

Groovy, 68 bytes

f=-n;s.eachMatch(/.{1,$n}/){printf "%${f}s%n",f>0?it[-1..0]:it;f=-f}

revised after I realized the initial version didn't handle padding correctly.

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Java 8, 197 146 136 bytes

s->n->{String r="",t,u;for(int l=s.length,i=0,j;i<l/n*n+n;r+=t+"\n",i=j)for(t="",j=i;j<i+n;t=j++/n%2<1?t+u:u+t)u=j<l?s[j]:" ";return r;}

Try it online.

Explanation:

s->n->{                 // Method with String and integer parameters and String return-type
  String r="",          //  Result-String, starting empty
         t,u;           //  Temp-Strings
  for(int l=s.length,   //  Length of the input-String
      i=0,j;i<l/n*n+n   //  Loop `i` in the range [0, `l` + whatever to make blocks of `n`)
      ;                 //    After every iteration:
       r+=t+"\n",       //     Append the result-String with `t` and a new-line
       i=j)             //     And set `i` to `j`
    for(t="",           //   Reset `t`
        j=i;j<i+n;      //   Inner loop `j` in the range [i, i+n)
        ;t=j++/n%2<1?   //     After every iteration: If the k'th block of `n` is even:  
            t+u         //      Append `u` to `t`
           :            //     Else (it's odd):
            u+t)        //      Prepend `u` to `t`
      u=j<l?            //    If `j` is still within bounds:
         s[j]           //     Set `u` to the current character
        :               //    Else:
         " ";           //     Set `u` to a space
  return r;}            //  Return the result-String
\$\endgroup\$
1
\$\begingroup\$

C (gcc), 145 141 bytes

Not allowing trailing whitespace made it clunkier than otherwise.

Thanks to ceilingcat for the tip that led me on the track to save 4 bytes.

f(s,n,l,i,j)char*s;{for(l=strlen(s),i=0;i<l;i+=2*n)if(printf("%-*.*s\n",n,n,s+i),i+n<l){for(j=i+2*n;j>i+n;)putchar(l/j--?s[j]:32);puts("");}}

Try it online!

\$\endgroup\$
0
1
\$\begingroup\$

Japt, 14 bytes

óV y £Yv ?X:Xw

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Pip, 34 bytes

Fla.sXb-#(@RVa<>b)<>b{Po?lRVlo!:o}

Similar approach as to my Boustrophedonise answer, but with padding and splitting the string.

Try it online!

\$\endgroup\$
1
\$\begingroup\$

05AB1E, 22 bytes

ô0UεRDg²s-úXÈiR}X>U}}»

Try it online!

Bring on the golfing suggestions!

\$\endgroup\$
1
\$\begingroup\$

Jelly, 8 bytes

sz⁶ZUÐeY

Try it online!

s           Slice the left argument into pieces (right argument) long.
 z          Zip it with filler
  ⁶         " ",
   Z        zip it back,
    U       reverse the slices
     Ðe     at even 1-indices,
       Y    and join on newlines.
\$\endgroup\$
1
\$\begingroup\$

Brachylog, 20 bytes

⟨{ġ|,Ṣ↰}lᵛ⟩{i↔ⁱ⁾}ᶠ~ṇ

Try it online!

Takes input as a list [string, slice length].

⟨{     }                To the string, apply the following predicate:
  ġ                     split it into slices of roughly equal length,
   |                    or
    ,Ṣ                  append a space
      ↰                 and recur.
        lᵛ⟩             ...such that each slice has the prescribed length.
                  ~ṇ    The output, split on newlines, is
           {    }ᶠ      every possible result from
            i           taking a slice with its 0-index
             ↔          and reversing
               ⁾        the slice
              ⁱ⁾        a number of times equal to the index.

I'm a bit ashamed to have only come up with this the moment I had finished explaining my previous solution:

Brachylog, 22 bytes

{|,Ṣ↰}ʰġ₎z₂z{i↔ⁱ⁾c}ᶠ~ṇ

Try it online!

      ʰ                   Apply the following predicate to the input string:
{|                        leave it unchanged, or
  ,Ṣ                      append a space
    ↰}                    and recur.
       ġ                  Split the string into slices
        ₎                 of the given length (except maybe the last one).
         z₂z              Each slice has the same length.
                    ~ṇ    The output, split on newlines, is
            {     }ᶠ      every possible result from
             i            taking a slice with its 0-index
              ↔           and reversing
                ⁾         the slice
               ⁱ⁾         a number of times equal to the index
                 c        (then concatenating it, as the zipping exploded it).
\$\endgroup\$
1
\$\begingroup\$

Python 3, 95 bytes

s,z=eval(input());p=0
while p<len(s):a=s[p:p+z].ljust(z);print(a[::-1] if p%(2*z) else a);p+=z

Try it here online: https://ideone.com/F4aY4d

\$\endgroup\$
2
0
\$\begingroup\$

Ruby, 80

->s,l{s+=' '*(l-s.size%l)
(s.size/l).times{|i|puts [x=s[i*l,l],x.reverse][i%2]}}

Online demo: http://ideone.com/w6o8PI

\$\endgroup\$
1
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.