27
\$\begingroup\$

I thought of a new way to generate my passwords, and even though it's probably not very clever in the long run, it could still make for a fun code-golf.

Taking a string of words, the password is generated thus:

  • Pick the nth character in the nth word
  • If n is larger than the word, continue counting backwards

Example:

This is a fun task!
T     s a  u      !

T is the first character
s is the second
a is the first, but going back and forth it is also the third
u is the second but because of counting backwards it's also the fourth
'!' is the fifth character in 'task!' and thus will be included in the final password, Tsau!

Rules

  • Input will be a string
  • Separate the string on spaces, all other characters must be included
  • Uppercase letters must remain uppercase, same with lowercase
  • You take n steps in each word, where n is the number of words that have come before plus one
  • If n is larger than the word, you must step backwards through the word, if you hit the start, you go forward again until you have stepped n times
  • The first and last character is only stepped once, so 'fun' on the seventh position as an example goes 'funufun' and ends on n, not 'funnuff' and ends on f
  • Output must be a string

Examples:

Input              Output
Once Upon A Time   OpAe
There was a man    Taaa
Who made a task    Waak
That was neat!     Taa
This is a long string to display how the generator is supposed to work  Tsagnoyotoipto

The shortest code in bytes wins!

\$\endgroup\$
7
  • 3
    \$\begingroup\$ to is the 12th word (0-indexed) in the long string, and therefore the code letter should be t, not o. \$\endgroup\$
    – Neil
    May 31, 2018 at 8:21
  • \$\begingroup\$ @Neil <s>the sequence is 1-indexed, otherwise you can't start with the first letter on the first word</s> (I tried) my bad, I see it now \$\endgroup\$ May 31, 2018 at 8:38
  • 16
    \$\begingroup\$ Tsau! is chinese for Fuck! \$\endgroup\$
    – sergiol
    May 31, 2018 at 18:05
  • 1
    \$\begingroup\$ Also your stepping plan for choosing funufun over funnuff will increase the percentage of vowels in the output. Cryptographically, this is not a strong password generator. \$\endgroup\$
    – Criggie
    Jun 1, 2018 at 3:19
  • 1
    \$\begingroup\$ @Criggie I never intended to use it, but as I said, it would make for a fun challenge, and it appears that the golfers agree \$\endgroup\$ Jun 1, 2018 at 5:19

23 Answers 23

13
\$\begingroup\$

Python 2, 72 bytes

lambda s:''.join((-~i*(w+w[-2:0:-1]))[i]for i,w in enumerate(s.split()))

Try it online!

\$\endgroup\$
7
\$\begingroup\$

05AB1E, 11 bytes

#vyN©Fû}®è?

Try it online!

Explanation

#             # split input on spaces
 vy           # for each word in input
   N©F        # N times do, where N is the current iteration
      û}      # palendromize the word
        ®è    # use N to index into the resulting word
          ?   # print
\$\endgroup\$
1
4
\$\begingroup\$

Jelly, 12 bytes

ḲJị"ŒBṖȯ$€$Ɗ

Try it online!

\$\endgroup\$
4
\$\begingroup\$

Java 10, 148 117 114 110 bytes

s->{int i=-1,j;for(var a:s.split(" "))System.out.print(a.charAt((j=a.length()-1)>0*i++?i/j%2<1?i%j:j-i%j:0));}

-31 bytes thanks to @SamYonnou by creating a port of @user71546's JavaScript answer.
-4 bytes thanks to @SamYonnou again, optimizing the algorithm for Java.

Try it online.

Explanation:

s->{                            // Method with String parameter and no return-type
  int i=-1,                     // Step integer, starting at -1
      j;                        // Temp integer
  for(var a:s.split(" "))       // Loop over the parts split by spaces
    System.out.print(           // Print:
     a.charAt((j=a.length()-1)  //  Set `j` to the the length of the part minus 1
               >0               //  If the length of the part is larger than 1 (`j` > 0)
                 *i++?          //  (and increase `i` by 1 in the process with `i++`)
                i/j%2<1?        //   If `i` integer-divided by `j` is even:
                 i%j            //    Print the character at index `i` modulo-`j`
                :               //   Else:
                 j-i%j          //    Print the character at index `j` minus `i` modulo-`j`
               :                //  Else:
                0));}           //   Print the first (and only) character
                                //   (the >0 check is added to prevent divided-by-0 errors)
\$\endgroup\$
5
  • \$\begingroup\$ Doesn't work for test cases 0, 2 and 5 \$\endgroup\$
    – TFeld
    May 31, 2018 at 8:24
  • 1
    \$\begingroup\$ golfed down to 117 "using a more arithmetic approach" similar to what user71546's version seems to be doing: s->{int i=-1,j;for(var a:s.split(" ")){System.out.print(a.charAt(++i>(j=a.length()-1)?j>0?i/j%2==0?i%j:j-i%j:0:i));}} \$\endgroup\$
    – SamYonnou
    May 31, 2018 at 19:31
  • 1
    \$\begingroup\$ @SamYonnou Thanks! And I've been able to golf three more bytes by removing the brackets and changing ==0 to <1. \$\endgroup\$ May 31, 2018 at 21:42
  • 1
    \$\begingroup\$ golfed to 110 by getting rid of the ++i>(j=a.length()-1) condition since the math works the same way regardless of the result of that condition: s->{int i=-1,j;for(var a:s.split(" "))System.out.print(a.charAt(0<(j=a.length()+i-++i)?i/j%2<1?i%j:j-i%j:0));} \$\endgroup\$
    – SamYonnou
    Jun 1, 2018 at 14:21
  • 1
    \$\begingroup\$ @SamYonnou Thanks again! I've slightly changed 0<(j=a.length()+i-++i)? to (j=a.length()-1)>0*i++? so the explanation was a bit easier to type (no bytes saved doing so however). \$\endgroup\$ Jun 1, 2018 at 15:07
3
\$\begingroup\$

Charcoal, 16 bytes

⭆⪪S §⁺ι✂ι±²¦⁰±¹κ

Try it online! Link is to verbose version of code. Explanation:

  S                 Input string
 ⪪                  Split on spaces
⭆                   Map over words and join
      ι ι           Current word
       ✂ ±²¦⁰±¹     Slice backwards from 2nd last character to start exclusive
     ⁺              Concatenate
    §          κ    Cyclically index on current word index
                    Implicitly print

I don't often get to use Slice's last parameter.

\$\endgroup\$
1
  • \$\begingroup\$ I like that Charcoal uses a scissors glyph \$\endgroup\$
    – Jonah
    Jun 1, 2018 at 14:18
3
\$\begingroup\$

Stax, 9 bytes

éñ~╗D¡┤Gq

Run and debug it

Unpacked, ungolfed, and commented, it looks like this.

j       split into words
{       start block for mapping
  cDrD  copy word; remove first and last character; reverse
  +     concatenate with original word
  i@    modularly (wrap-around) index using map iteration index
m       perform map

Run this one

\$\endgroup\$
3
\$\begingroup\$

JavaScript (Node.js), 78 70 69 68 bytes

-1 byte @Arnauld

x=>x.split` `.map((y,i)=>y[a=i%(l=y.length-1)|0,i/l&1?l-a:a]).join``

Try it online!

Explanation

x=>
 x.split` `                    // Split the words by spaces
 .map((y,i)=>                  // For each word:
  y[                           //  Get the character at index:
                               //   A walk has cycle of length (2 * y.length - 2)
   a=i%(l=y.length-1)|0,       //   Calculate index a = i % (y.length - 1)
   i/l&1                       //   Check in which half the index i in
   ?l-a                        //   If in the second half of cycle, use y.length - 1 - a
   :a                          //   If in the first half of cycle, use a                  
  ]
 ).join``                      // Join back the letters
\$\endgroup\$
0
2
\$\begingroup\$

Red, 135 bytes

func[s][n: 0 p: copy""foreach w split s" "[append/dup r: copy""append w
reverse copy/part next w back tail w n: n + 1 append p r/(n)]p]

Try it online!

Readable:

f: func[s][
    n: 0
    p: copy ""
    foreach w split s "  "[
        r: copy ""
        append/dup r append w reverse copy/part next w back tail w n: n + 1
        append p r/(n)
    ]
    p
]
\$\endgroup\$
2
\$\begingroup\$

Perl 5, 76 bytes

print map{$l=length;substr$_.reverse,$i++%(2*$l-2||1)*(1+1/$l),1}split" ",<>

Try it online!

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

k, 31 30 28 bytes

{x{*|y#x,1_|1_x}'1+!#x}@" "\

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ |-1_ -> 1_| \$\endgroup\$
    – ngn
    Jun 2, 2018 at 19:22
  • \$\begingroup\$ you can save 2 bytes by swapping the inner lambda's arguments \$\endgroup\$
    – ngn
    Jun 3, 2018 at 16:15
2
\$\begingroup\$

Husk, 14 11 bytes

SzS!ö!…¢ŀŀw

Try it online! Inspiration was taken from this program by Zgarb for the forward-and-reverse stepping.

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

Pyth, 12 bytes

s.e@+b_Ptbkc

Try it online

s.e@+b_PtbkcQ   Final Q (input) implicit

           cQ   Split on spaces
 .e             Map the above with b=element, k=index
       Ptb        Remove 1st and last character
      _           Reverse
    +b            Prepend the unaltered element ('abcd' -> 'abcdcb')
   @      k       Get the kth character (0 indexed, wrapping)
s               Join on empty string, implicit output
\$\endgroup\$
1
\$\begingroup\$

Japt, -P, 11 bytes

¸Ëê ŪD gEÉ

Try it

¸Ë+s1J w)gE

Try it


Explanations

¸Ëê ŪD gEÉ
¸               :Split on spaces
 Ë              :Map over each element D at index E
  ê             :  Palindromise
    Å           :  Slice off the first character
     ªD         :  Logical OR with the original element (the above will return an empty string for single character words)
        g       :  Get the character at index
         EÉ     :  E-1
¸Ë+s1J w)gE
¸               :Split on spaces
 Ë              :Map over each element D at index E
   s1J          :  Slice off the first and last characters
       w        :  Reverse
  +     )       :  Append to D
         gE     :  Get the character at index E
\$\endgroup\$
1
\$\begingroup\$

C (gcc), 148 bytes (string version), 114 bytes (print version)

If I must return a string (long version):

char c[99]={0};char*f(s,t,u,i,j,k)char*s,*t,*u;{for(u=c,i=0;t=strtok(s," ");s=0,i++)*u++=t[j=strlen(t),k=2*j-(j>1)-1,(i%k<j?i%k:k-i%k)%j];return c;}

Try it online!

Otherwise, I just print and don't worry about a buffer (short version):

f(s,t,i,j,k)char*s,*t;{for(i=0;t=strtok(s," ");s=0,i++)putchar(t[j=strlen(t),k=2*j-(j>1)-1,(i%k<j?i%k:k-i%k)%j]);}

Try it online!

\$\endgroup\$
5
  • \$\begingroup\$ -(j>1)-1 can be replaced by +~(j>1) with 1 byte less I think. \$\endgroup\$ Jun 1, 2018 at 7:02
  • \$\begingroup\$ 106 chars: putchar( t[ j=strlen(t)-1, k = i++ % (j ? j*2 : 1), k<j ? k : j+j-k ]); Try it online! \$\endgroup\$ Jun 2, 2018 at 23:06
  • \$\begingroup\$ Buffered version: Global variables are implicitly zeroed. Replace *u++ with c[i] and remove u. \$\endgroup\$ Jun 3, 2018 at 0:13
  • \$\begingroup\$ Building on @user5329483 105 bytes \$\endgroup\$
    – ceilingcat
    Dec 28, 2018 at 19:13
  • \$\begingroup\$ Building on @ceilingcat 103 bytes \$\endgroup\$
    – c--
    Oct 18, 2022 at 1:50
1
\$\begingroup\$

AWK, 79 bytes

Mostly because I'm curious to see any better awk or bash solutions!

{for(i=1;i<=NF;i++){l=length($i);k=int(i/l)%2?l-i%l:k%l;printf substr($i,k,1)}}

Try it online!

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

C# (.NET Core), 111 bytes

s=>{int i=-1,j;return String.Concat(s.Split(' ').Select(a=>a[++i>(j=a.Length-1)?j>0?i/j%2<1?i%j:j-i%j:0:i]));};

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Welcome to PPCG. Nice answer \$\endgroup\$ Jun 1, 2018 at 13:25
1
\$\begingroup\$

Haskell, 65 62 61 bytes

zipWith(\i->(!!i).cycle.(id<>reverse.drop 1.init))[0..].words

Try it online!

It requires the latest version of Prelude which features the <> function.

                   words    -- split the input string into a list of words
zipWith(\i->     )[0..]     -- zip the elements i of [0..] and the words pairwise
                            -- with the function      
      ... <> ...            --   call the functions with a word and concatenate
                            --   the results. The functions are
        id                  --     id: do nothing
        reverse.drop 1.init --     drop last and first element and reverse
    cycle                   --   repeat infinitely
(!!i)                       -- take the ith elemnt of  

Edit: -3 bytes thanks to @user28667, -1 byte thanks to @B. Mehta

\$\endgroup\$
2
  • \$\begingroup\$ Looks like zipWith(\i w->(cycle$id<>reverse.drop 1.init$w)!!i)[0..].words also works. \$\endgroup\$
    – user28667
    May 31, 2018 at 15:52
  • 1
    \$\begingroup\$ You can save another byte by changing the lambda to \i->(!!i).cycle.(id<>reverse.drop 1.init) factoring out the explicit w mention (TIO) \$\endgroup\$
    – B. Mehta
    Jun 1, 2018 at 11:40
1
\$\begingroup\$

PHP, 77 bytes

while(ord($w=$argv[++$i]))echo($w.=strrev(substr($w,1,-1)))[~-$i%strlen($w)];

Try it online!

  • -3 bytes thanks to Kevin
  • -10 bytes thanks to Titus
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Nice answer! One small thing to golf: you can get rid of the brackets and one additional third byte by changing foreach(...){$c=...;echo$c[...];} to foreach(...)echo($c=...)[...];. Try it online: 87 bytes \$\endgroup\$ May 31, 2018 at 14:55
  • \$\begingroup\$ You can use the argument list to automatically split to words (-8 bytes), and .= saves two bytes: while(ord($w=$argv[++$i]))echo($w.=strrev(substr($w,1,-1)))[~-$i%strlen($w)]; try it online \$\endgroup\$
    – Titus
    Jun 2, 2018 at 10:53
  • \$\begingroup\$ Nice! One question: ~-$i does the same as ($i-1), right? \$\endgroup\$ Jun 3, 2018 at 9:57
1
\$\begingroup\$

Vyxal, 11 bytes

⌈₅(ʁ):ẏ¨£i∑

Try it Online!

⌈           # Input split on spaces
 ₅( )       # repeat len(that) times...
   ʁ        # Palindromise each word
       ¨£   # Zipping...
     :      # Words
      ẏ     # range(0, len(words))
         i  # Index the numbers into the words
          ∑ # Stringify
\$\endgroup\$
1
  • \$\begingroup\$ 10: ⌈₅(ʁ)¨2i;∑ (8 with s flag) \$\endgroup\$
    – naffetS
    Oct 18, 2022 at 0:54
0
\$\begingroup\$

Powershell 208 186 170 bytes

$args|%{$i=0;-join($_.Split()|%{$l=($b=($a=$_)).Length;if($l-gt2){$b=($a|%{-join$a[($l-2)..1]})}for($j=0;$a.Length-le$i;$j++){$a+=($b,$_)[$j%2]}$a.Substring($i,1);$i++})}

Ungolfed:

$args|%{
   $i=0;
    -join($_.Split()|%{
        $l=($b=($a=$_)).Length;
        if($l-gt2){
            $b=($a|%{-join$a[($l-2)..1]})
        }
        for($j=0;$a.Length-le$i;$j++){
            $a+=($b,$_)[$j%2]
        }
        $a.Substring($i,1);
        $i++
    })
}

Test cases below or try it online

@(
    "This is a fun task!",
    "Once Upon A Time",
    "There was a man",
    "Who made a task",
    "That was neat",
    "This is a long string to display how the generator is supposed to work"
)|%{$i=0;-join($_.Split()|%{$l=($b=($a=$_)).Length;if($l-gt2){$b=($a|%{-join$a[($l-2)..1]})}for($j=0;$a.Length-le$i;$j++){$a+=($b,$_)[$j%2]}$a.Substring($i,1);$i++})}
\$\endgroup\$
4
  • 1
    \$\begingroup\$ There's a lot you could make shorter here. Have you see the tips for golfing in PowerShell? \$\endgroup\$
    – briantist
    Jun 2, 2018 at 15:57
  • \$\begingroup\$ Thanks! I’d thought about using switch just after posting, but the rest hadn’t occurred to me yet. \$\endgroup\$ Jun 2, 2018 at 15:59
  • \$\begingroup\$ Also one actual problem here is that you don't really take input anywhere in this snippet. We're pretty flexible about being able to write a program or function, but yours has implicit input. As a first step you might simply replace your ""|%{ with $args|%{, but I think you can golf it more effectively too ;) \$\endgroup\$
    – briantist
    Jun 2, 2018 at 16:10
  • 1
    \$\begingroup\$ Here's a demonstration in TIO that also shows how to use the arguments feature for test cases. Keeping the code block for your code only also let's you use TIO's easy linking and byte counts for your post! \$\endgroup\$
    – briantist
    Jun 2, 2018 at 16:10
0
\$\begingroup\$

J, 43 bytes

[:(>{~"_1#@>|i.@#)[:(,}.@}:)&.>[:<;._1' '&,

ungolfed

[: (> {~"_1 #@> | i.@#) [: (, }.@}:)&.> [: <;._1 ' '&,
  • <;._1 ' '&, split on spaces
  • (, }.@}:)&.> for each word, kill the first and last elm and append to word
  • #@> | i.@# take the remainder of each word's length divided into its index
  • > {~"_1 take that result and pluck it from each word.

Try it online!

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

CJam, 22 bytes

qS/{_);1>W%+T_):T@*=}%

Try it online!

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

Ruby -pl, 60 bytes

gsub(/(\S+) ?/){w=$1+$1.reverse[1..-2]
w[(-2+$.+=1)%w.size]}

Attempt This Online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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