15
\$\begingroup\$

The Challenge

Given an input string (or array) consisting of < and >, output a sequence (array or string) of integers such that:

  • the operators are all correct when applied in order between consecutive numbers in the output
  • all integers are positive (1 or greater)
  • the sum of the integers is as small as is mathematically possible

Inputs can vary to match "greater than" and "less than" in your chosen language.

As an alternative output, just specify the sum of the numbers in the output. State which version you're solving in your Answer title.

Usual exclusions and rules apply, smallest bytes wins.

You can assume that the input string will never lead to an integer overflow in your language, if that helps.

Examples

  • > gives 2 1 which sums to 3
  • >>> gives 4 3 2 1 which sums to 10
  • >< gives 2 1 2 which sums to 5
  • gives 1 which sums to 1
  • >>>>>>>>> gives 10 9 8 7 6 5 4 3 2 1 which sums to 55
  • >><<>><>>> gives 3 2 1 2 3 2 1 4 3 2 1 which sums to 24
  • ><>><>><> gives 2 1 3 2 1 3 2 1 2 1 which sums to 18
  • <<<<> gives 1 2 3 4 5 1 which sums to 16
  • <<<<><<> gives 1 2 3 4 5 1 2 3 1 which sums to 22
  • >><< gives 3 2 1 2 3 which sums to 11
\$\endgroup\$
10
  • \$\begingroup\$ Can we use symbols other than > and <? \$\endgroup\$ Mar 29, 2018 at 17:11
  • \$\begingroup\$ @JonathanAllan I think it's the examples that are wrong, and you should assume that when answering, not that the spec is wrong. EDIT: Well, then I'm afraid they're invalid, since it's the spec that defines a challenge, not the test cases. \$\endgroup\$ Mar 29, 2018 at 17:50
  • 4
    \$\begingroup\$ Just waitin' for an answer in <><. \$\endgroup\$ Mar 29, 2018 at 21:24
  • 1
    \$\begingroup\$ Massive apologies to everyone for messing up the examples! As for other characters, yes provided they have the same meaning in your language \$\endgroup\$ Mar 29, 2018 at 21:55
  • 3
    \$\begingroup\$ @Scrooble You spelled it wrong. It's ><> \$\endgroup\$
    – Jo King
    Mar 30, 2018 at 1:09

10 Answers 10

8
\$\begingroup\$

><>, 40 38 bytes

1v!rnr~<oa
?\i:0(?^3%\+$
{/?:-{:}-1/1:

Try it online!

An appropriate language. For reference ><> itself yields 2,1,2,1.

How it Works:

1v   Initialise the stack as 1 and enter loop
 \i:0(?^  If we're out of input, go to the first line
        3%\ Otherwise mod the input by 3, yielding 0 for < and 2 for >
        -1/Subtract 1 to get -1 and 1 respectively
    -{:}   Copy the previous number and subtract the above from it

 /?:    If the number is not 0, repeat the loop

?\        \+$  Otherwise:
                Increment each number until we reach the original 0
{/        /1:   And enter the first loop again

      ~<    When we're out of input, pop the extra -1 from EOF
   rnr      Output the first number
1v!         Push a 1 
        oa  Print a newline and repeat, popping the extra 1 each time
\$\endgroup\$
1
  • \$\begingroup\$ +1 for stating what value the language itself holds. :) (And because it's just a good answer as well, otherwise I wouldn't have +1-ed it.) \$\endgroup\$ Mar 30, 2018 at 7:27
5
\$\begingroup\$

Python 3, 93 bytes

k=0
for r in input().split('<'):p=len(r);print(max(k,p)+1,*range(p,0,-1),end=' ');k=1+(p<1)*k

Try it online!

Unscrambled:

# offset, will be explained later
k = 0 
for run in input().split('<'):
    # p = length of sequence of '>'s, which will produce p+1 decreasing integers
    p = len(run)
    # will print:
    # p+1 p p-1 ... 1    or    k+1 p p-1 ... 1
    print(max(k, p) + 1, *range(p, 0, -1), end=' ')
    # offset of the next sequence: (i.e. -1 + the minimal value of the first integer)
    k = 1 + (k if p > 0 else 0)
\$\endgroup\$
1
  • 1
    \$\begingroup\$ This is my first golf! \$\endgroup\$
    – Fons
    Mar 30, 2018 at 13:17
5
\$\begingroup\$

Haskell, 119 bytes

n%">"=r[1..n]
n%"<"=[1..n]
n%(c:b)|c==b!!0=(n+1)%b|a:s<-2%b,e:z<-r$n%[c]=r z++last(max:[min|c>'<'])a e:s
r=reverse
(2%)

Try it online!

Explanation

The idea here is that we have runs of either >s or <s, which each map to ascending and descending ranges. So we use group to split the string into groups of consecutive characters. Our job is to then stitch these together in the proper fashion.

When we have <> we want to stitch the two lists together taking the larger end value for example

<<<<<<>>

is split

<<<<<<  >>

mapped to ranges

[1,2,3,4,5,6,7] [3,2,1]

Then when we stitch we drop 3 because it is smaller (3 isn't larger than 7).

 [1,2,3,4,5,6,7,2,1]

When we have >< we do the opposite, we drop the larger value.

The actual code attains this by making an operator %. The definition of % is quite complex, but basically it reads from left to right keeping track of how many consecutive characters are the same. It does this in the left had value of the operator. When we reach a place where the characters change we perform the stitching as I described.

\$\endgroup\$
7
  • \$\begingroup\$ What's the purpose of the last line (2%)? \$\endgroup\$
    – siracusa
    Mar 29, 2018 at 22:36
  • \$\begingroup\$ @siracusa That is the function itself. It is a pointfree function, so it basically says call % with 2 as the first argument. \$\endgroup\$
    – Wheat Wizard
    Mar 29, 2018 at 23:05
  • \$\begingroup\$ Is that a common practice here to just put the final function call on the last line instead of adding a full main implementation? \$\endgroup\$
    – siracusa
    Mar 29, 2018 at 23:30
  • 1
    \$\begingroup\$ @siracusa Yes. Submissions are allowed as named functions, anonymous functions or as complete programs. This is an anonymous function. I choose anonymous simply because it is the shortest. \$\endgroup\$
    – Wheat Wizard
    Mar 29, 2018 at 23:37
  • \$\begingroup\$ @siracusa See our Guide to Golfing Rules in Haskell. \$\endgroup\$
    – Laikoni
    Mar 30, 2018 at 10:24
4
\$\begingroup\$

Retina 0.8.2, 36 bytes


1
{`\b(1+)>\1
1$&
}`(1+)<\1\b
$&1
1

Try it online! Link includes test cases. Explanation:


1

Insert 1s before, between and after the <s and >s.

{`\b(1+)>\1
1$&
}`(1+)<\1\b
$&1

Repeatedly increment integers until all the comparisons are satisfied.

1

Sum the integers and convert to decimal.

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

Jelly, 19 bytes

0;+×¥@\
=”<µCṚÇṚ»Ç‘

Try it online!

The value of each number is max( number of > immediately to the right of it , number of < immediately to the left of it ) + 1 .


Alternatively...

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ I don't like languages requiring a program to transpile like Stax... well, Jelly is borderline. (require a program to compress strings) At least, Jelly still wins. \$\endgroup\$
    – DELETE_ME
    Mar 30, 2018 at 10:22
  • \$\begingroup\$ except Dennis, who compresses strings by hand. \$\endgroup\$
    – DELETE_ME
    Mar 30, 2018 at 10:45
  • \$\begingroup\$ Aesthetically, I don't really like it either. But the thing I like most of all in a golfing language is whatever allows its programs to be smallest. I still have a few ideas for stax about this one... \$\endgroup\$
    – recursive
    Mar 30, 2018 at 21:54
3
\$\begingroup\$

Haskell, 87 bytes

r=reverse
s#c=(+1).length.takeWhile(==c)<$>scanr(:)[]s
f s=zipWith max(s#'>')$r$r s#'<'

Try it online!

A port of my Jelly answer.

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

Java 10, 198 181 180 bytes

s->{var p=s.split("(?<=(.))(?!\\1)");int l=p.length,L[]=new int[l],i=l,r=0,a,b;for(;i-->0;r-=a*~a/2+(i<l-1?p[i].charAt(0)<61?a<(b=L[i+1])?a:b:1:0))a=L[i]=p[i].length()+1;return r;}

-1 byte thanks to @ceilingcat.

Try it online.

Explanation:

s->{                     // Method with String parameter and integer return-type
  var p=s.split("(?<=(.))(?!\\1)");
                         //  Split the String into parts
                         //  (i.e. ">><<>><>>>" becomes [>>, <<, >>, <, >>>])
  int l=p.length,        //  Get the amount of parts
      L[]=new int[l],    //  Create an integer-array of the same size
      i=l,               //  Index-integer, starting at this size
      r=0,               //  Result-integer, starting at 0
      a,b;               //  Two temp integers to reduce the byte-count
  for(;i-->0;            //  Loop downwards over the array; range: (`l`,0]
      ;r-=               //    After every iteration: decrease the result with:
          a*~a/2         //     The negative triangle number of the current item
        +                //     And add to that negative triangle number before subtracting:
         (i<l-1?         //      If it's not the last item:
           p[i].charAt(0)<61?
                         //       And the order of the current and previous is "<>":
            a<(b=L[i+1])?//        If the current item in `L` is smaller than the previous:
             a           //         Add the current item
            :            //        Else (the current is equal or larger than the previous):
             b           //         Add the previous item
           :             //       Else (the order of the two parts is "><" instead):
            1            //        Add 1
          :              //      Else (it's the last item in `L`):
           0))           //       Leave the result `r` unchanged by adding 0
    a=L[i]=              //   Set both `a` and the current item in `L` to:
     p[i].length()+1;    //    The length of the part + 1
  return r;}             //  Return the result
\$\endgroup\$
0
2
\$\begingroup\$

Stax, 21 bytes

éda╓~/└↨☺∟╒←║ç Γφ5←9h

Run and debug it

It works by run-length encoding the input, and then concatenating generated ranges together. Unpacked, ungolfed, and commented, it looks like this.

|R      run-length encode
{       begin block
  H^R   range from [1 .. run length]
  _hh|1 -1 ** (character code / 2)
  *     multiply run; this will reverse it iff character is '>'
m       map runs using preceding block
O       push a 1 under the top of stack
{       begin block
  h|M   get the start of the generated range, and take max of it and top of stack
  _DE   push the rest (tail) of the generated range to the stack
F       foreach generated range
L|+     sum of all values on the stack

Run this one

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

Perl 5 -p, 53 bytes

#!/usr/bin/perl -p
s//1/g;1while s/(?=\b(1+)>\1)|(1+)<\2\b\K/1/;$_=y/1//

Try it online!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ This answer seems to have been implemented based off of the test cases instead of the challenge specification. Unfortunately, they have been identified as wrong. \$\endgroup\$ Mar 29, 2018 at 17:58
  • 1
    \$\begingroup\$ @EriktheOutgolfer Fixed \$\endgroup\$
    – Ton Hospel
    Mar 30, 2018 at 10:08
1
\$\begingroup\$

Red, 185 bytes

func[s][repeat n 1 + length? s[l: 0 i: n - 1 while[i > 0 and(s/(i) = #"<")][i:  i - 1 l: l + 1]r: 0 i: n while[(i <= length? s)and(s/(i) = #">")][i: i + 1 r:
r + 1]prin[1 + max l r""]]]

After user202729's explanation...

Try it online!

f: func[s][
   repeat n 1 + length? s[
       l: 0
       i: n - 1
       while [i > 0 and (s/(i) = #"<")][ 
           i: i - 1
           l: l + 1
        ]
        r: 0
        i: n
        while [(i <= length? s) and (s/(i) = #">")][
            i: i + 1
            r: r + 1
        ]
        prin[1 + max l r ""]
    ]
]
\$\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.