23
\$\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\$
  • 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 '18 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\$ – Troels M. B. Jensen May 31 '18 at 8:38
  • 14
    \$\begingroup\$ Tsau! is chinese for Fuck! \$\endgroup\$ – sergiol May 31 '18 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 '18 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\$ – Troels M. B. Jensen Jun 1 '18 at 5:19

19 Answers 19

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\$
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\$
  • \$\begingroup\$ Doesn't work for test cases 0, 2 and 5 \$\endgroup\$ – TFeld May 31 '18 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 '18 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\$ – Kevin Cruijssen May 31 '18 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 '18 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\$ – Kevin Cruijssen Jun 1 '18 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\$
  • \$\begingroup\$ I like that Charcoal uses a scissors glyph \$\endgroup\$ – Jonah Jun 1 '18 at 14:18
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\$
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\$
  • \$\begingroup\$ |-1_ -> 1_| \$\endgroup\$ – ngn Jun 2 '18 at 19:22
  • \$\begingroup\$ you can save 2 bytes by swapping the inner lambda's arguments \$\endgroup\$ – ngn Jun 3 '18 at 16:15
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\$
  • \$\begingroup\$ -(j>1)-1 can be replaced by +~(j>1) with 1 byte less I think. \$\endgroup\$ – Shieru Asakoto Jun 1 '18 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\$ – user5329483 Jun 2 '18 at 23:06
  • \$\begingroup\$ Buffered version: Global variables are implicitly zeroed. Replace *u++ with c[i] and remove u. \$\endgroup\$ – user5329483 Jun 3 '18 at 0:13
  • \$\begingroup\$ Building on @user5329483 105 bytes \$\endgroup\$ – ceilingcat Dec 28 '18 at 19:13
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\$
  • \$\begingroup\$ Welcome to PPCG. Nice answer \$\endgroup\$ – Muhammad Salman Jun 1 '18 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\$
  • \$\begingroup\$ Looks like zipWith(\i w->(cycle$id<>reverse.drop 1.init$w)!!i)[0..].words also works. \$\endgroup\$ – user28667 May 31 '18 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 '18 at 11:40
1
\$\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\$
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\$
  • 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\$ – Kevin Cruijssen May 31 '18 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 '18 at 10:53
  • \$\begingroup\$ Nice! One question: ~-$i does the same as ($i-1), right? \$\endgroup\$ – user2803033 Jun 3 '18 at 9:57
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\$
  • 1
    \$\begingroup\$ There's a lot you could make shorter here. Have you see the tips for golfing in PowerShell? \$\endgroup\$ – briantist Jun 2 '18 at 15:57
  • \$\begingroup\$ Thanks! I’d thought about using switch just after posting, but the rest hadn’t occurred to me yet. \$\endgroup\$ – Peter Vandivier Jun 2 '18 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 '18 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 '18 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\$

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.