27
\$\begingroup\$

Vyxal is a stack-based language, meaning that everything operates by popping and pushing values onto a stack. It has a bunch of useful flags, one of which is r.

Running a Vyxal program with the r flag causes functions to take their elements in reverse order.

For example, the program 5 3 - means: Push 5 to stack, push 3 onto the stack, and subtract them by popping 3, popping 5, and subtracting the 3 from the 5 to yield 2. But with the r flag, it first pops the 5, then the 3, and subtracts 5 from 3 to yield -2.

For this challenge, we will be operating within a much-simplified version of Vyxal.

The digits 0-9 each push themselves to the stack , and lowercase letters are dyadic functions, meaning they pop two values from the stack and do something with them, before pushing the result. Everything else does nothing and won't be included in the input.

Your challenge is to take a program with this format and output a program that would do the same thing if the input order of each function is reversed.

This sounds complicated, so let's demonstrate with this example:

87a

To do this, we simply swap the 8 and the 7 to yield 78a.

A more complicated example:

54a78bc

How it works:

      c # c is a function taking...
   78b  # This, where:
     b  # b is a function taking
   78   # 7 and 8
        # And...
54a     # This, where:
  a     # a is a function taking... 
54      # 5 and 4 

So to flip it, we just flip the operands of every function:

  <-->
<->|| c 
|| 78b
54a |
 |  |
 <-->

Yielding:

87b45ac

Which is the result!

Another way to explain this is:

An operator is one of a-z

A token is either a single digit, or of the format [TOKEN][TOKEN][OPERATOR]

For each token of the format [TOKEN][TOKEN][OPERATOR], flip the two tokens.

Scoring

This is , shortest wins!

Testcases

You can assume there will always be two values to pop whenever there's a function/operator.

123ab => 32a1b
59a34bz => 43b95az
123456abcde => 65a4b3c2d1e
1 => 1
12a53bx7c08d9ef => 980de735b21axcf
12a34bc56d78efg => 87e65df43b21acg

As usual, these are created by hand, so please tell me if they're wrong.

\$\endgroup\$
4
  • \$\begingroup\$ Sandboxed \$\endgroup\$
    – emanresu A
    Jul 9, 2021 at 11:22
  • 1
    \$\begingroup\$ Will the program always end with only one value on the stack? That is true of all the test cases, but it isn't stated. \$\endgroup\$
    – m90
    Jul 9, 2021 at 12:56
  • 1
    \$\begingroup\$ Can we assume the input is non-empty? \$\endgroup\$
    – hyper-neutrino
    Jul 9, 2021 at 15:29
  • \$\begingroup\$ @hyper-neutrino Yes \$\endgroup\$
    – emanresu A
    Jul 9, 2021 at 20:32

17 Answers 17

40
\$\begingroup\$

05AB1E, 15 12 10 9 bytes

-1 byte thanks to Kevin Cruijssen!

This could be 8 bytes without the l, but why would I remove that?

vyxaliŠìì

Try it online!

v             # for each character y:
 y            #   push y
  x           #   duplicate TOS and double the copy
              #   double is a noop on alphabetic strings
   a          #   is the doubled copy alphabetic / the current char a function?
    l         #   convert the result to lowercase
     i        #   if the command was a function:
              #     stack before: [..., x1, x2, f]
      Š       #     triple-swap:  [..., f, x1, x2]
       ì      #     prepend:      [..., f, x2x1]
        ì     #     prepend:      [..., x2x1f]
\$\endgroup\$
5
  • 6
    \$\begingroup\$ Love the Vyxal in your code! \$\endgroup\$
    – user
    Jul 9, 2021 at 14:01
  • 4
    \$\begingroup\$ Did you set out to specifically write a solution with that sequence of characters in it or was it just a happy coincidence? \$\endgroup\$
    – Shaggy
    Jul 9, 2021 at 14:50
  • 5
    \$\begingroup\$ @Shaggy the l is actually just there for the joke. I had vy (very common pattern) and à initially and then noticed how close to vyxal this already was. Adding the x actually made me think of a shorter approach that saved two bytes, though using D instead would be a bit more idiomatic here. The a, which is a built-in I initially forgot about, happened to save another byte. \$\endgroup\$
    – ovs
    Jul 9, 2021 at 15:07
  • 5
    \$\begingroup\$ This is very cool. 10/10 \$\endgroup\$
    – lyxal
    Jul 10, 2021 at 7:43
  • 1
    \$\begingroup\$ You can remove the leading S for -1 \$\endgroup\$ Aug 23, 2021 at 9:16
13
\$\begingroup\$

brainfuck, 83 bytes

,[[>+>>>++++[>]<-<<[>]<<-]>>>>[-]<[+<<<<[<]<[[->+<]<]>+[>]>-[<<[<]>+[>]>-]]<,]<[.<]

Try it online!

Maintains a stack of tokens. When an operator is read, append it to the top two tokens on the stack. Each token should be read from right to left.

For each character in input:
,[
  Move forward one cell and compare to 85
  [>+>>>++++[>]<-<<[>]<<-]

  Clean up comparison cell
  >>>>[-]<

  If greater than 85 (and thus is operator):
  [
    Remove comparison result
    +

    Append last two tokens together
    <<<<[<]<[[->+<]<]>

    Append operator to end of this token
    +[>]>-[<<[<]>+[>]>-]
  ]
  <
,]
<[.<] output result
\$\endgroup\$
12
\$\begingroup\$

Vyxal, 18 12 8 bytes

(n:Ǎ[∇pp

Try it Online!

-5 thanks to @AUsername

and -1 to an extra golf on that golf

but then another -4 from A Username

The irony here is that using the r flag makes this way too long.

Explained

(n:Ǎ[∇pp
(              # for each character in the input:
 n:Ǎ           #     remove all letters from that character - if this is a letter, it will leave an empty string. Otherwise, it will leave it as-is.
    [          #     if the result isn't empty:
     ∇         #          rotate the top three items
      pp       #          and double prepend
\$\endgroup\$
2
9
\$\begingroup\$

K (ngn/k), 34 33 bytes

{$[y<58;x,y;(-2_x),,(,/2#|x),y]}/

Try it online!

A single neat K scan.

Returns a singleton list with the output.

-1 byte from Traws.

Explanation

{$[y<58;x,y;(-2_x),,(,/|-2#x),y]}/
{                               }/ scan from left
 $[                            ]   if
   y<58;                           current command <58 (is digit)
        x,y                        then join the two
           ;                       otherwise
                    (,/|-2#x)      join the last two commands, reversed
                             ,y    concat with current command
            (-2_x),,               nest, and  join with the rest of the output
\$\endgroup\$
1
  • \$\begingroup\$ -1 byte with: |-2#x -> 2#|x \$\endgroup\$
    – Traws
    Aug 3, 2021 at 19:09
8
\$\begingroup\$

JavaScript (ES6),  52  49 bytes

Expects an array of characters. Returns a string.

a=>a.map(c=>a.push(o=1/c?c:a.pop()+a.pop()+c))&&o

Try it online!

Commented

a =>                // a[] = input array, re-used as the stack
  a.map(c =>        // for each character c in a[]:
    a.push(         //   push in the stack ...
      o =           //     ... the new value o:
        1 / c ?     //       if c is a digit:
          c         //         just use c
        :           //       else:
          a.pop() + //         use the concatenation of
          a.pop() + //         the last 2 values from the stack
          c         //         followed by c
    )               //   end of push()
  ) && o            // end of map(); return the last value
\$\endgroup\$
7
\$\begingroup\$

Haskell, 55 bytes

head.foldl(%)[]
s%x|x<'a'=[x]:s
(a:b:s)%x=(a++b++[x]):s

Try it online!

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

Charcoal, 14 bytes

FS⊞υ⁺⭆⊗№βι⊟υιυ

Try it online! Link is to verbose version of code. Explanation: Based on @Arnauld's answer; for every input character, if it is a letter then pop the top two elements off the result stack and concatenate the three, otherwise just push the digit to the stack, however in Charcoal it turns out to be golfier to pop N elements off the result stack where N is 2 for a letter and 0 for a digit, and concatenate the character.

FS

Loop over the characters of the input string.

⊞υ⁺⭆⊗№βι⊟υι

Count the number of appearances of the character in the predefined lowercase alphabet, double that, pop that many terms from the predefined empty list, join everything together, and push that to the list.

υ

Output the final result.

\$\endgroup\$
3
  • \$\begingroup\$ This looks very clever but I can't follow the explanation. Do you mind elaborating it a bit? \$\endgroup\$
    – Jonah
    Jul 9, 2021 at 18:23
  • 1
    \$\begingroup\$ @Jonah I've done the best I can... \$\endgroup\$
    – Neil
    Jul 9, 2021 at 18:48
  • \$\begingroup\$ Tyvm. It's clear to me now. \$\endgroup\$
    – Jonah
    Jul 9, 2021 at 19:48
3
\$\begingroup\$

Stax, 10 bytes

ªç8îá/╤╫╬∩

Run and debug it

same idea as my K answer.

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

Jelly, 17 bytes

;ṭ@Ṫ,Ṫ{;ʋ¥ØDi¥}?/

Try It Online!

Since the input is guaranteed to be non-empty (clarified by OP), we do not need to reduce from an initial value and can replace ƒ“” with / (thanks to Leaky Nun for -2 bytes).

There's gotta be a better way to get rid of that ṭ@Ṫ,Ṫ{;ʋ¥ mess in the middle.

;ṭ@Ṫ,Ṫ{;ʋ¥ØDi¥}?/    Main Link
                /    Reduce
               ?     If
              }      - The right argument
            i          - Appears in
          ØD           - "0123456789"
;                    - Append it to the accumulating stack
                     Otherwise
 --======¥           - Previous two; 2,2-chain x (a b) y = x a (x b y)
 ṭ@                  - Append to the accumulator the result of
   -=--=ʋ            - Previous four; 1,2,2,2-chain x (A b c d) y = (x A) b (x c y) d y
   Ṫ                   - Pop the last element off the stack
    ,                  - And pair it with
     Ṫ{                - Pop the last element off the left side (the stack)
       ;               - Append the incoming character
\$\endgroup\$
3
  • 1
    \$\begingroup\$ I'm finding a ton of stuff that ties this, but nothing shorter. This would probably be the craziest of them. \$\endgroup\$ Jul 9, 2021 at 15:49
  • 1
    \$\begingroup\$ You don't need to reduce from the empty string \$\endgroup\$
    – Leaky Nun
    Jul 9, 2021 at 18:41
  • 1
    \$\begingroup\$ @LeakyNun Thanks. I considered that but it will error if the input is empty. I don't know if we can assume it will be non-empty; I've asked OP to clarify that (and another comment asking for clarification may clear that up too). \$\endgroup\$
    – hyper-neutrino
    Jul 9, 2021 at 18:50
3
\$\begingroup\$

Python 3, 81 77 bytes

Python port of the Javascript answer

A recursive lambda might solve this with fewer bytes though.

-4 bytes thanx to ovs

def f(i,s=[]):
 for c in i:s+=[c<'a'and c or s.pop()+s.pop()+c]
 return s[-1]

Try it online!

\$\endgroup\$
5
  • 1
    \$\begingroup\$ This is currently not a valid submission as we require functions to be reusable, which this one is not. But this can be fixed by returning the last value in s with s[-1], which is even shorter \$\endgroup\$
    – ovs
    Jul 9, 2021 at 16:20
  • 1
    \$\begingroup\$ This also ties exactly while being reusable, if you can think of a further golf from there \$\endgroup\$ Jul 9, 2021 at 18:22
  • \$\begingroup\$ I can't see where to use s[-1] here, so updated with @UnrelatedString's fix. \$\endgroup\$
    – movatica
    Jul 12, 2021 at 18:06
  • 1
    \$\begingroup\$ When the function is done s only contains a single string, now you can do ''.join(s) -> s[0]. Another way to make this reusable is this: tio.run/… \$\endgroup\$
    – ovs
    Jul 12, 2021 at 20:38
  • \$\begingroup\$ oh, of course, didn't think that one through! \$\endgroup\$
    – movatica
    Jul 13, 2021 at 19:57
3
\$\begingroup\$

Factor, 71 bytes

EBNF: A e=e e[a-z]=>[[first3 1string surround]]|[0-9]=>[[1string]];EBNF

Try it online!

EBNF definition strikes again :) Defines a function named A which takes a string, parses it, and returns its r-flagged version as a string.

(TIO version is slightly older than 0.98 stable, and requires ending ;EBNF instead of surrounding the body with [=[ ]=]. The TIO version happens to be shorter.)

A bit of jankiness comes from the fact that the character class [0-9] gives its charcode, not any kind of sequence (array, vector, or string). 1string is used to keep all intermediate results as strings.

Ungolfed

! If part of a postfix expression,
! parse the two operands and the operator, swap the operands, and concatenate
expr = expr expr [a-z] => [[ first3 1string surround ]]
! Otherwise, take a single digit operand and make it a string
     | [0-9] => [[ 1string ]]
\$\endgroup\$
3
\$\begingroup\$

APL (Dyalog Extended), 27 bytes

∊{⍺∊⎕D:⍺,⍵⋄(2↑⍵)⍺⊂⍛,2↓⍵}/⍤⌽

Try it online!

Straightforward reduction, as in many other answers. Since APL's reduction is from right to left, the reduction is done on the input string reversed. Also, the top of the stack is on the left side, and the stack items are kept nested until the very end (where flattens the entire structure).

APL (Dyalog Extended), 34 bytes

{⍵[⍒∊{0 2 1⊂⍤+@⍺∊3×⍵}/⌽0,⍸~⍵∊⎕D]}⌽

Try it online!

I had an idea of grade-and-indexing, where base 3 numbers define the ordering of elements. It works well, but it is unfortunately slightly longer than the easy solution.

This works by reconstructing the postfix structure based on the indices of operators.

Input: '59a34bz' (expected output: '43b95az')

{...}⌽  Reverse the string and pass onto the dfn.
        This has the structure of prefix notation, with args swapped.
        ⍵←'zb43a95'
⍸~⍵∊⎕D  Extract the (1-based) indices of operators.
        v←1 2 5
{...}/⌽0,  Reverse v and reduce on it with the starting value of 0.
           ⍺ gets the indices (1, 2, then 5), and ⍵ is the current vector.
∊3×⍵    Multiply all numbers in ⍵ by 3 and flatten it.
0 2 1⊂⍤+@⍺  Add 0 2 1 to the ⍺-th element in ⍵, creating a nested vector.
        ⍺←1, ⍵←0: ⊂(0 2 1)
        ⍺←2, ⍵←↑: 0 2 1 → 0 6 3 → 0(6 8 7)3
        ⍺←5, ⍵←↑: 0 6 8 7 3 → 0 18 24 21 9 → 0 18 24 21(9 11 10)
⍵[⍒∊...]  Flatten the final result, and sort ⍵ by descending order of that.
        Flatten:   0 18 24 21 9 11 10
        Input(⍵):  z  b  4  3 a  9  5
        Sort desc: 43b95az
\$\endgroup\$
2
\$\begingroup\$

Retina 0.8.2, 29 bytes

S`\B
+1`(.+)¶(.+)¶(\D)
$2$1$3

Try it online! Link includes test cases. Explanation:

S`\B

Split each character onto its own line. (Sadly _S doesn't seem to do what I want.)

+1`(.+)¶(.+)¶(\D)
$2$1$3

Processing each operator in turn, prefix it with its reversed operands.

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

J, 41 bytes

[:|.@;((;@;1 0&{);2}.])`;@.(58>3 u:[)/@|.

Try it online!

Well, this is quite long and inelegant because of the required boxing in J. Perhaps someone can suggest a better approach.

I believe the current approach is doing more or less the same thing as Razetime's K answer.

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

Japt v2.0a0 -h, 15 bytes

Input as a character array, output as a string.

£pXiUoX²è\a)¬)Ì

Try it

£pXiUoX²è\a)¬)Ì     :Implicit input of array U
£                   :Map each X
 p                  :  Push to U
  Xi                :    Prepend to X
    Uo              :      Pop this many elements from U
      X²            :        Duplicate X
        è           :        Count occurrences of
         \a         :        RegEx /[a-z]/g
           )        :      End pop
            ¬       :      Join
             )      :  End push
              Ì     :  Last element
                    :Implicit output of last element of resulting array
\$\endgroup\$
2
\$\begingroup\$

Vim, 51 bytes

:s/./\r&/g
qq{:/\v(.+)\n(.+)\n(\a)/s//\2\1\3
@qq@qJ

Try it online!

The J can be omitted if a leading newline is permissible.

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

Python 3, 80 bytes

f=lambda i,o=[]:i and f(i[1:],o+[(i[0]>'9'and o.pop()+o.pop()or'')+i[0]])or o[0]

Try it 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.