30
\$\begingroup\$

Challenge

Robin likes having his variables declaration in the shape of an arrow. Here's how he does it:

  • Input any number of strings
  • Order them by ascending length
  • Output them ordered by the middle to roughly form a negative arrowhead, like this (whichever order golfs the best):

    5  or  4
    3      2
    1      1
    2      3
    4      5
    

Test Cases

Input:

bow
arrows
sheriffOfNottingham
kingRichard
maidMarian
princeJohn
sherwoodForest

Output:

sheriffOfNottingham
kingRichard
maidMarian
bow
arrows
princeJohn
sherwoodForest

Input:

a
bb
cc

Output (both are valid):

bb
a
cc

cc
a
bb

Input:

one
four
seven
fifteen

Possible output (the only other valid output is its vertical mirror):

seven
one
four
fifteen

Notes

  • The strings are in camelCase and have no numbers or special characters, only lowercase and uppercase letters.

  • The input can be anything you like: comma-separated as one string, array, ... Any I/O format is allowed.

  • Between strings with the same length, any order is accepted.
\$\endgroup\$
11
  • 1
    \$\begingroup\$ I feel like there was a very similar challenge before...but welcome to PPCG! \$\endgroup\$
    – Giuseppe
    Commented Apr 3, 2019 at 16:48
  • \$\begingroup\$ @Giuseppe Yeah that's what I thought after posting, there's no way it hasn't been done before. Would you be ok with me deleting it now that you've answered it? \$\endgroup\$ Commented Apr 3, 2019 at 16:54
  • 1
    \$\begingroup\$ well I've been searching for a dupe but I'm not very good at the search...we do have a sandbox for posting challenges which can often catch things like that. I'm perfectly OK with you deleting it if you're worried about it being a dupe. \$\endgroup\$
    – Giuseppe
    Commented Apr 3, 2019 at 16:55
  • 1
    \$\begingroup\$ It's OK, we all start from the beginning :-) \$\endgroup\$
    – Giuseppe
    Commented Apr 3, 2019 at 17:06
  • 1
    \$\begingroup\$ Could you add a test case with an even number of strings? \$\endgroup\$
    – Sherlock9
    Commented Apr 3, 2019 at 17:22

28 Answers 28

15
\$\begingroup\$

Python 2, 47 bytes

lambda l:l.sort(key=len)or l[1::2][::-1]+l[::2]

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ You'll need to rearrange some stuff, but you can use [::-2] directly to save 5 bytes. \$\endgroup\$
    – Sherlock9
    Commented Apr 3, 2019 at 17:03
  • \$\begingroup\$ @Sherlock9 I tried that, but then I had to check for the length, as lists with even / uneven lengths have to be handled differently. \$\endgroup\$
    – ovs
    Commented Apr 3, 2019 at 17:06
  • \$\begingroup\$ Also works for Python 3. Would removing "lambda l:" and "or" and make it on 2 lines to save 11 bytes still be acceptable as "Any I/O format is allowed" ? \$\endgroup\$
    – potato
    Commented Apr 5, 2019 at 13:54
9
\$\begingroup\$

R, 63 48 bytes

function(L)c(rev(o<-L[order(nchar(L))]),o)[!0:1]

Try it online!

Sort by string lengths, then combine the reversed list with the sorted list, finally, take every 2nd element, starting at 1-based index 1.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ o<-L[... The other way to 'arrow variables'. A less important aside, pryr::f(...) works here for 46. Try it online! \$\endgroup\$ Commented Apr 4, 2019 at 7:40
  • \$\begingroup\$ @CriminallyVulgar using additional libraries turns this into a separate language, R + pryr which is why I typically avoid doing it unless there's a good reason to -- like for number theory questions, numbers is indispensable. \$\endgroup\$
    – Giuseppe
    Commented Apr 8, 2019 at 15:02
7
\$\begingroup\$

Javascript 77 bytes

Takes input as an array of strings, outputs an arrow-sorted array of strings.

s=>s.sort((a,b)=>a.length-b.length).reduce((m,x,i)=>i%2?[...m,x]:[x,...m],[])

Explanation

s =>                                 // take input as an array of strings s
  s.sort((a,b)=>a.length-b.length)   // sort input by string length
  .reduce(                           // reduce
    (m,x,i)=>i%2?[...m,x]:[x,...m],  // if index is even, stick string x at the end of the memo
                                     // array, else at the beginning
    []                               // memo initialized to empty array
  )
\$\endgroup\$
4
  • 1
    \$\begingroup\$ I don't think you have to count f=. 77 \$\endgroup\$
    – dana
    Commented Apr 4, 2019 at 11:54
  • \$\begingroup\$ That is inconsistent in the js code golf submissions from what I have seen. I'm happy to exclude it if it doesn't count. \$\endgroup\$
    – asgallant
    Commented Apr 4, 2019 at 16:11
  • 2
    \$\begingroup\$ I think it depends whether your function uses recursion. i.e. f=x=>x?f(x-1). If so, you need to include f since you are calling it in your function. However, since you are not using recursion, you shouldn't have to include f. There are several posts in Meta, this one seems to explain it a little better. codegolf.meta.stackexchange.com/a/9032/8340 \$\endgroup\$
    – dana
    Commented Apr 4, 2019 at 16:34
  • \$\begingroup\$ That would explain the inconsistencies I've seen. \$\endgroup\$
    – asgallant
    Commented Apr 4, 2019 at 16:54
6
\$\begingroup\$

Ruby, 51 bytes

->l{r=1;l.sort_by!(&:size).map{l[r-=2]||(l*2)[~r]}}

Try it online!

\$\endgroup\$
5
\$\begingroup\$

C# (Visual C# Interactive Compiler), 89 bytes

n=>(n=n.OrderBy(x=>x.Length)).Where((a,b)=>b%2>0).Reverse().Concat(n.Where((a,b)=>b%2<1))

Try it online!

\$\endgroup\$
5
\$\begingroup\$

K (oK), 24 bytes

Solution:

x(<#:'x)(|&~w),&w:2!!#x:

Try it online!

Explanation:

Generate the 6 4 2 0 1 3 5 sequence, use that to index into the ascending lengths of input, and use that to index into the original array:

x(<#:'x)(|&~w),&w:2!!#x: / the solution
                      x: / save input as x
                     #   / count (#) of x
                    !    / range 0 to ...
                  2!     / modulo 2
                w:       / save as w
               &         / indices where true
              ,          / join with
        (    )           / do this together
           ~w            / not (~) w
          &              / indices where true
         |               / reverse
 (     )                 / do this together
   #:'x                  / count (#:) of each (') x
  <                      / indices to sort ascending
x                        / index into x
\$\endgroup\$
0
5
\$\begingroup\$

Jelly, 9 8 bytes

LÞŒœm"-Ẏ

Try it online!

LÞŒœṚ;¥/

is also 8 bytes.

Thanks to @EriktheOutgolfer and @JonathanAllan for both offering golfs to save a byte.

\$\endgroup\$
2
  • \$\begingroup\$ Nice! Clever golf: Ṛ€1¦ can become m"-. \$\endgroup\$ Commented Apr 3, 2019 at 18:38
  • \$\begingroup\$ Or you could go for LÞŒœṚ;¥/ \$\endgroup\$ Commented Apr 3, 2019 at 18:49
5
\$\begingroup\$

05AB1E, 6 5 bytes

Saved 1 byte thanks to Kevin Cruijssen

I/O is a list of strings.
Link is modified for newline separated I/O for easier testing.

éι`Rì

Try it online!

Explanation

é       # sort by length ascending
 ι      # uninterleave into 2 parts, both sorted ascending
   `    # push the 2 parts separately to the stack
    R   # reverse the second part
     ì  # and append it to the first
\$\endgroup\$
2
  • \$\begingroup\$ You can remove the first R and replace « with i to save a byte, since the third bullet-point rule allows both versions of uninterleaving. \$\endgroup\$ Commented Apr 4, 2019 at 7:00
  • \$\begingroup\$ @KevinCruijssen: Oh yeah, Thanks! \$\endgroup\$
    – Emigna
    Commented Apr 4, 2019 at 9:14
5
\$\begingroup\$

J, 11 bytes

,~`,/@\:#&>

Try it online!

We sort it down first.

Then we reduce the list form right to left, but alternating which side we put the new element on. Done.

\$\endgroup\$
2
  • \$\begingroup\$ Very nice! You have a space at the end though, remove it for 11 bytes :) \$\endgroup\$ Commented Apr 4, 2019 at 6:18
  • 1
    \$\begingroup\$ Thanks Galen. Fixed! \$\endgroup\$
    – Jonah
    Commented Apr 4, 2019 at 10:01
4
\$\begingroup\$

PowerShell, 66 bytes

1..($a=$args|sort l*).count|?{$_%2}|%{$a[-$_];$x=,$a[-++$_]+$x};$x

Try it online!

Takes input via splatting, which manifests on TIO as separate command-line arguments. sorts on the length, stores that into $a, and constructs a range from 1 up to the count of input strings. We then pull out only the odd ones ?{$_%2} and feed those into a loop |%{...}. Each iteration, we put the "last", then the "third from last", and so on onto the pipeline with $a[-$_]. Separately, we also accumulate into $x the "second from last", "fourth from last", etc. Out of the loop and the pipeline is flushed (so those elements are output) and then we output $x. In both instances, the default output gives us newlines between items automatically.

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

PHP, 144 141 bytes

function($a){usort($a,function($b,$c){return strlen($b)-strlen($c);});$e=[];foreach($a as$d)(array_.[unshift,push][++$i%2])($e,$d);return$e;}

Try it online!

-3 bytes thanks to @Ismael Miguel!

\$\endgroup\$
5
  • \$\begingroup\$ nice one. Where can I read more about [array_unshift,array_push][++$i%2]($e,$d)? \$\endgroup\$
    – abhig10
    Commented Apr 4, 2019 at 10:15
  • 2
    \$\begingroup\$ @abhig10 sure. It's an array with the two function names ['array_push','array_unshift'] with [++$i%2] as the index of the array alternating between a 0 or 1 so will evaluate to the other function each time. PHP's "variable functions" let you assign a varible to a function and execute by calling with parenthesis (ex: $f='array_push'; $f($e,$d); == array_push($e,$d)) so the ($e,$d) is then calling the evaluated element of the array. Just a shorter way to do if (++$i%2) array_push($e,$d); else array_unshift($e,$e);. Guess there was some PHP syntactic sugar after all! \$\endgroup\$
    – 640KB
    Commented Apr 4, 2019 at 14:33
  • \$\begingroup\$ Okay, it took me sometime to understand this. Awesome. \$\endgroup\$
    – abhig10
    Commented Apr 4, 2019 at 15:21
  • 1
    \$\begingroup\$ You can save 3 bytes by replacing [array_unshift,array_push][++$i%2]($e,$d) with (array_.[unshift,push][++$i%2])($e,$d). What I did was to remove the repeated array_, concatenated it and then the result is passed to the call. \$\endgroup\$ Commented Apr 5, 2019 at 15:07
  • 1
    \$\begingroup\$ @IsmaelMiguel that's brilliant. Thank you! \$\endgroup\$
    – 640KB
    Commented Apr 5, 2019 at 15:13
4
\$\begingroup\$

MATLAB, 87 bytes

function f(y);[B,I]=sort(cellfun(@(x)length(x),y));{y{flip(I(1:2:end))},y{I(2:2:end)}}'

Takes input as cell array of strings, outputs column of strings (not sure if that's legal)

> s = {'qweq qwe qw','qweqw','12132132131231231','asdasdasda','qwe','w'};
> f(s)
> >> 
> ans =
> 
>   6×1 cell array
> 
>     {'qweq qwe qw'      }
>     {'qweqw'            }
>     {'qwe'              }
>     {'1234'             }
>     {'asdasdasda'       }
>     {'12132132131231231'}

PS: Thanks Sanchises for pointing to a bug with odd-length inputs

\$\endgroup\$
11
  • \$\begingroup\$ This fails on odd number of input strings, e.g. f({'loooooooong','medium','short'}) \$\endgroup\$
    – Sanchises
    Commented Apr 4, 2019 at 9:38
  • \$\begingroup\$ Also some general golfing tips: the end is optional for a function. Using function x=f(y);x={...}' is shorter than function f(y);disp({...}'). \$\endgroup\$
    – Sanchises
    Commented Apr 4, 2019 at 9:43
  • \$\begingroup\$ If you're stuck, here's how I would do it. \$\endgroup\$
    – Sanchises
    Commented Apr 4, 2019 at 9:54
  • \$\begingroup\$ @Sanchises thanks for pointing bug out. I did fix it exactly like you did. My issue with disp is i am not sure what output rules are. Should it be pure text or not? or disp({...}) is okay or even just x={...} as you suggest \$\endgroup\$ Commented Apr 4, 2019 at 16:36
  • 1
    \$\begingroup\$ This can be 58 bytes in Octave. \$\endgroup\$
    – Giuseppe
    Commented Apr 5, 2019 at 17:34
3
\$\begingroup\$

APL (Dyalog Unicode), 18 bytesSBCS

{⍵[⍋-@(2∘|)⍋⍋≢¨⍵]}

Try it online!

Fixed the bug thanks to @ngn.

Explanation:

{⍵[⍋-@(2∘|)⍋⍋≢¨⍵]}
{                } ⍝ Function. Takes a single argument: ⍵, list of strings
             ≢¨⍵   ⍝ The length of each element in the list
           ⍋⍋      ⍝ Sort the lengths
    -@(2∘|)        ⍝ At (@) elements divisible by 2 (|), negate (-)
                   ⍝     gives -1 2 -3 4 -5
   ⍋               ⍝ Sort this list again, gives the indices of that list ^ sorted
 ⍵[             ]  ⍝ Use these indices to index into the argument

¹

\$\endgroup\$
2
  • 1
    \$\begingroup\$ ≢¨×¯1*⍳∘⍴ -> (⊢∘-\≢¨) and it gets even shorter if you turn it into a dfn \$\endgroup\$
    – ngn
    Commented Apr 7, 2019 at 4:58
  • 1
    \$\begingroup\$ however, i'm not sure this algorithm is correct. we should negate the length of every other string in their sorted order, not in the order they come from the input \$\endgroup\$
    – ngn
    Commented Apr 7, 2019 at 5:14
2
\$\begingroup\$

APL+WIN, 31 38 bytes

See Adams comment

⊃n[(⍳⍴n)~a],⌽n[a←2×⍳⌊.5×⍴n←n[⍒∊⍴¨n←⎕]]

Try it online Courtesy of Dyalog Classic!

Prompts for a nested vector of strings

\$\endgroup\$
3
  • \$\begingroup\$ Does APL+ not have Monadic "tally" to replace ∊⍴ ? \$\endgroup\$
    – Adám
    Commented Apr 3, 2019 at 19:02
  • 1
    \$\begingroup\$ Fails on '12' '1234' '1234' '1234' '1234' '12345678' '12345678' '12345678' '12345678'. Clearly, the result should have been '12345678' '12345678' '1234' '1234' '12' '1234' '1234' '12345678' '12345678' \$\endgroup\$
    – Adám
    Commented Apr 3, 2019 at 19:06
  • \$\begingroup\$ @Adám My ancient version of APL+ does not have ≢. Agreed on your second comment I will take a look at it tomorrow. \$\endgroup\$
    – Graham
    Commented Apr 3, 2019 at 19:26
2
\$\begingroup\$

Retina, 26 bytes

N$`
$.&
*\,2,^A`.+
,2,G`.+

Try it online! Explanation:

N$`
$.&

Sort the lines in ascending order of length ($.& returns the length of the line).

*\,2,^A`.+

Temporarily delete alternate lines and output the remaining lines in reverse order.

,2,G`.+

Keep the only lines that were temporarily deleted and output them.

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

Gaia, 10 bytes

el∫v:v+2%ụ

Try it online!

e		| eval as Gaia code (list of strings)
 l∫		| ∫ort by lengths (ascending)
   v:v		| reverse, dup, reverse
      +		| concatenate lists
       2%	| take every other element
         ụ	| join by newlines and output
\$\endgroup\$
1
  • 5
    \$\begingroup\$ i like that your comments in unwrapped code form an arrow of strings \$\endgroup\$ Commented Apr 3, 2019 at 23:47
2
\$\begingroup\$

Japt, 8 bytes

ñÊó g0_w

-3 bytes thanks to Shaggy!

Try it

\$\endgroup\$
4
  • \$\begingroup\$ 10 bytes with output as a 2D-array, which would seem to be allowed. \$\endgroup\$
    – Shaggy
    Commented Apr 3, 2019 at 21:28
  • \$\begingroup\$ Or, maybe, 8 bytes? On my phone so haven't tested it properly. \$\endgroup\$
    – Shaggy
    Commented Apr 3, 2019 at 21:30
  • \$\begingroup\$ @Shaggy I was looking for a function to find every nth element, but I couldn't find it. Thanks! \$\endgroup\$
    – Gymhgy
    Commented Apr 3, 2019 at 21:37
  • \$\begingroup\$ there's also A.ë() but I don't know if that'll lead to a shorter solution. \$\endgroup\$
    – Shaggy
    Commented Apr 3, 2019 at 21:45
2
\$\begingroup\$

PowerShell, 49 bytes

$args|sort l*|sort{$_.Length*($global:x=-$x*2+1)}

Try it online!

The double distillation.

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

T-SQL, 84 bytes

Input is a table variable

SELECT a FROM(SELECT*,row_number()over(order by len(a))r
FROM @)x order by(r%2-.5)*r

Try it online

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

Perl 6, 31 bytes

*.sort(&chars).sort:{$++%2*$--}

Try it online!

Sort by string length, then by static sequence 0, -1, 0, -3, 0, -5, ...

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

Javascript 95 Bytes

s=>s.sort((x,y)=>x.length-y.length).reduce((a,e,i)=>{i%2?a.push(e):a.unshift(e);return a;},[]);
\$\endgroup\$
2
  • \$\begingroup\$ -1 s.sort() sorts the strings lexicographically, not by string length. \$\endgroup\$
    – asgallant
    Commented Apr 3, 2019 at 19:34
  • \$\begingroup\$ Right, (x,y)=>x.length-y.length, should fix that. \$\endgroup\$
    – somsom
    Commented Apr 3, 2019 at 19:41
1
\$\begingroup\$

Red, 116 101 bytes

func[b][sort/compare b func[x y][(length? x)> length? y]collect[forall b[keep take b]keep reverse b]]

Try it online!

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

perl 5 (-p0777F/\n/ -M5.01), 59 bytes

for$x(sort{$b=~y///c-length$a}@F){--$|?$\="$x
".$\:say$x}}{

TIO

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

C (gcc), 136 128 bytes

S(a,b)int**a,**b;{a=strlen(*b)-strlen(*a);}f(l,s,o,i,b,e)int**s,**o;{qsort(s,l,8,S);e=l-1;for(i=b=0;i-l;)o[i++%2?b++:e--]=s[i];}

Try it online!

-8 bytes thanks to ceilingcat.

The function f is the solution. It takes the number of strings, the strings themselves, and the output buffer as arguments (plus four more used internally).

\$\endgroup\$
5
  • \$\begingroup\$ Why is ./.bin.tio in the output? \$\endgroup\$ Commented Apr 3, 2019 at 22:27
  • \$\begingroup\$ @TeleportingGoat Probably because their footer is using all of argv, which includes the filename \$\endgroup\$
    – Jo King
    Commented Apr 4, 2019 at 1:46
  • \$\begingroup\$ Exactly, it was just a quick test. One can construct any data that takes appropriate format. I'll update the TIO link later. \$\endgroup\$
    – LambdaBeta
    Commented Apr 4, 2019 at 13:42
  • \$\begingroup\$ haha, the problem with these short variable names: you forget what you hat t for in the first place and keep it around even when you don't need it! \$\endgroup\$
    – LambdaBeta
    Commented Apr 10, 2019 at 20:44
  • \$\begingroup\$ 122 bytes \$\endgroup\$
    – ceilingcat
    Commented Aug 13, 2019 at 19:51
1
\$\begingroup\$

Husk, 11 bytes

m!ÖL¹Ċ2§+ṡŀ

Try it online!

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

Vyxal a, 7 bytes

µL;yṘ$"

Try it Online!

Outputs as a list of two lists of lines.

The header and footer allow for multiline IO.

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

Japt, 8 6 bytes

Input as an array of lines, output as an array of 2 arrays of lines, one for each half of the list.

ñÊó vw

Try it (Header & footer allow for I/O as newline separated string)

ñÊó vw     :Implicit input of array
ñ          :Sort by
 Ê         :  Length
  ó        :Uninterleave
    v      :Modify first element
     w     :  Reverse
\$\endgroup\$
0
0
\$\begingroup\$

Julia 1.0, 41 bytes

!s=sort(s,by=length)[∪(end:-2:1,1:end)]

Try it online!

  • input and output are vectors of strings
  • end:-2:1 takes every second index, starting from the end
  • 1:end is all indices
  • (=union) removes duplicates
\$\endgroup\$

Your Answer

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

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