Brute-force the switchboard

32

1

The other day, our team went to an escape room. One of the puzzles involved a board of six mechanical switches where you had to find the correct combination of on and off in order to unlock a box, somewhat like this:

-v-v-v-
-v-v-v-

Being developers, we decided it would be more efficient to try every single one of 2^6=64 combinations than actually solve the puzzle. So we assigned some poor guy to do some binary counting:

-v-v-v-
-v-v-v-

-v-v-v-
-v-v-^-

-v-v-v-
-v-^-v-

-v-v-v-
-v-^-^-

and so on.

The challenge
Write a program that, given the switches all in off position as a string formatted as above, generates all combinations of on and off in any order.

You can write either a full program or a function. Thus, your program can either take in input through stdin, a file, or as a single string argument, and either return or print the output. If returned, the output may be in a list/array/etc. rather than a single string. If the output is a single string, the boards should be separated by newlines (trailing newlines are allowed.)

The input strings will match the regex r'((-v)+-)(\n(-v)+-)*' and represent one board with all switches off. This means no zero case, and switches are left-aligned. Each row might not have the same number of switches.

Each output board should be of the exact same format as the input, except that the v's may be replaced by ^'s as required. The output boards can be separated by any number of newlines.

Since runtime is naturally O(2^n) in the number of switches, your code will not be tested on any more than 10 switches in any arrangement.

This is code-golf, so shortest code in number of bytes wins.

Sample inputs and outputs

Input:

-v-

Possible output:

-v-
-^-

Input:

-v-
-v-

Possible output:

-^-
-^-
-^-
-v-

-v-
-^-


-v-
-v-

Since it's extremely tedious to check your answer for bigger numbers of switches, here's a Python script as a sanity check tool. (I've included a currently commented-out snippet to generate expected output from a given input file in case you want more test cases.) It's quite a bit less flexible in terms of input and output than the spec, unfortunately; put the input string in a file named 'input' and the newline-separated output (sorry, no list formatting) in a file named 'output' in the same directory and run python3 sanitycheck.py.

Rin's Fourier transform

Posted 2019-07-19T17:47:09.083

Reputation: 827

8nice first challenge! – Giuseppe – 2019-07-19T17:51:13.247

12

Hopefully, the "poor guy" knew about Gray code in order to only flip one bit between each combination.

– Eric Duminil – 2019-07-20T12:00:27.783

1Time is our most precious asset, don't waste it in vain. – Pedro Lobito – 2019-07-20T12:54:09.807

6Given the theme, I'm disappointed you didn't require an order that requires the least amount of toggles (e.g. 00->01->11->10 has 3 toggles while 00->01->10->11 has 4) -- Fellow brute force escaper – ikegami – 2019-07-20T18:43:54.427

@EricDuminil Lol yeah, we were all a little ignorant, thanks for enlightening me to that though – Rin's Fourier transform – 2019-07-20T19:57:45.290

@ikegami ah, fair, I thought it would be interesting to see the most golfy ways to fit them into each different programming language though rather than just one or two algorithms that everyone uses.

Even so, it looks like bunch of them did turn out to just be binary counting xd – Rin's Fourier transform – 2019-07-20T19:58:59.930

@Giuseppe and five others Thank you so much! I was super pleasantly surprised to wake up to 18 answers :v – Rin's Fourier transform – 2019-07-20T20:01:13.527

1

@ikegami That's the Gray code I was talking about.

– Eric Duminil – 2019-07-21T11:07:26.210

@Eric Duminil, Yeah. I only noticed that your comment was talking about the same thing far afterwards. – ikegami – 2019-07-21T11:36:21.707

2@EricDuminil: if the mechanical switches were not buttons (and maybe even if), then most likely, the difference the time needed between switching one, two and three consecutive switches (which you could probably do almost simultaneously) wouldn't be large enough to offset the extra mental work to follow the Gray code. – tomasz – 2019-07-21T15:26:37.217

1

@tomasz: Maybe. But aren't we all here for the "extra mental work"? When I'm afraid that a programming task is too complex or might take too long, I come back to read this answer.

– Eric Duminil – 2019-07-22T08:52:28.277

@EricDuminil: My point is, the extra mental work will give you overhead which might negate any (time) advantage that you would gain from not having to do as many individual switches (especially if you can switch several switches simultaneously). Which is bad if you are pressed for time, as you might be in an escape room. Indeed, the whole premise of this problem is doing brute force instead of doing the mental work and solving the puzzle. – tomasz – 2019-07-22T11:03:18.487

@PedroLobito "Don't waste it in vain" nice pleonasm! :) – Teleporting Goat – 2019-07-22T13:14:36.477

@teleporting-goat, time is always "wasted" because you cannot stop it, but you can choose to spend it wisely, not in vain. It may not make too much sense to french speakers, which is normal, since their preception of reality is normally distorted. – Pedro Lobito – 2019-07-23T02:42:21.767

@PedroLobito I'll pass on the personal attack on French speakers being 'not normal' and won't add anything else after this bc comments aren't for this, but no. To "waste time" is to spend time in vain, especially in your context. If it's spent cleverly and usefully, it's just spent. Time is wasted when something could be done faster or when you wait for nothing. You could literally have said "time is precious, don't waste it" or "don't spend it in vain" and the meaning would be basically the same. Perhaps it would help to look at definitions.

– Teleporting Goat – 2019-07-23T08:03:02.027

Answers

23

Haskell, 25 24 23 17 bytes

mapM$min"^v".pure

Try it online!

-1 byte thanks to @H.PWiz

-1 byte thanks to @nimi

Returns a list of strings. The TIO has 2 extra bytes for the function declaration - I've seen other people leave it off when they write the function pointfree so I'm doing the same unless told otherwise.

Previous Answer (25 bytes)

g 'v'="v^"
g x=[x]
mapM g

The explanations are all for the previous answer, which works pretty much the same way, except I inlined the definition of g. The way g works now is by using lexical comparison to substitute ^v for v and keep everything else the same.

Interestingly, this works for arbitrary switchboards:

>>> mapM g "-----^-----"
  ["-----v-----", "-----^-----"]

Explanation (Short)

g 'v'="v^" -- for 'v', choose between 'v' or '^'
g x=[x]    -- for any other character, choose just that character
mapM g     -- find all ways to choose characters using g on the given input

Explanation (Long)

mapM is a pretty scary function for those not familiar with Haskell. But it's not hard to understand in this context. By making it act on Strings (which in Haskell are lists of characters), I've specialized it to its definition for lists. So in this context, its type signature is

mapM :: (a -> [b]) -> [a] -> [[b]]
--      ^^^^^^^^^^                  arg 1: a function from any a to a list of b
--                    ^^^           arg 2: a list of a
--                           ^^^^^ return: a list of list of b

It is actually even more specialized in my usage of it - a and b are both Char - so we can see the type signature as

mapM :: (Char -> String) -> String -> [String]

Let's quickly look at what g does before explaining how mapM works.

g :: Char -> String
g 'v' = "v^"
g  x  = [x]

g uses pattern matching to convert the Char 'v' into the string "v^"; everything else gets converted to a singleton string (remember, strings are just lists of Chars, so we can put x in a singleton list). Testing on the REPL, we find this is the case

>>> g 'a'
  "a"
>>> g 'b'
  "b"
>>> g 'v'
  "v^"

Note that g has the right type to be an argument of mapM (unsurprisingly!).

We'll explore how mapM works by giving it g and the argument

"-v-\n-v-"

as input.

mapM first maps g over the String, and because g converts Chars to Strings, this gives us a list of Strings

["-", "v^", "-", "\n", "-", "v^", "-"]

While this is the correct output type, mapM does slightly more. You can think of it as forming all Strings that you could create from this list if you had to pick a single character from each String in it (in order).

So for the first element, you have no choice other than to pick the Char '-'. For the second element, you can choose between 'v' and '^', so on and so forth.

It's roughly equivalent to this python code:

result = []
for x1 in "-":
  for x2 in "v^":
    for x3 in "-":
      ...
        result.append(''.join([x1, x2, x3, x4, x5, x6, x7]))

Except that since Haskell separates between Chars and Strings, when it puts the Chars into a list, it doesn't need to join them.

So the final output is

["-v-\n-v-", "-v-\n-^", "-^-\n-v-", "-^-\n-^-"]

as desired.

cole

Posted 2019-07-19T17:47:09.083

Reputation: 3 526

Ooh, I've been waiting for a purely functional answer, this really blew me away at how concise it was. – Rin's Fourier transform – 2019-07-20T20:07:59.607

2@Rin'sFouriertransform I was pleased with how nicely mapM worked for this challenge, at first I had it formulated as sequence . map g but that can be expressed compactly as mapM id . map g and then I saw I could just mapM g – cole – 2019-07-20T20:27:58.063

1I think you can swap =='v' for >'-' – H.PWiz – 2019-07-20T20:29:34.270

9

Jelly, 7 bytes

«Ƭ€”^Œp

Try it online!

Output is a list of Jelly strings.

Explanation:

«Ƭ€”^Œp  Arguments: 1
«Ƭ€”^    Dyad-nilad pair
  €       Map over left argument
 Ƭ         Apply repeatedly until a result that has previously been seen is seen
           again, return original and intermediate results
«           Dyad: Minimum of arguments
   ”^     Nilad: Literal: '^'
         Note: 'v' is the only character that is greater than '^' and can
         appear in the input, so, while for every character c other than 'v'
         this operation returns [c], for 'v' it returns ['v', '^']. In this way,
         duplicates are never going to appear in the output.
     Œp  Monad: Cartesian product of elements

Erik the Outgolfer

Posted 2019-07-19T17:47:09.083

Reputation: 38 134

I've actually been scrambling through the Jelly code pages to try to figure out how the first answer has continually outgolfed every single other answer, almost always by a pretty good margin...would you care to explain how this works? – Rin's Fourier transform – 2019-07-20T20:03:36.840

@Rin'sFouriertransform I've added an explanation. – Erik the Outgolfer – 2019-07-20T21:51:16.397

9

Perl 6, 32 bytes

{[X~] .comb».&{$_,('^'if /v/)}}

Try it online!

  • .comb splits the string into characters.
  • ».&{...} maps the characters according to the function between the braces.
  • $_, ('^' if /v/) produces a list of alternates for each character. Only v has an alternate: ^.
  • [X~] reduces that list with the string-concatenation cross-product operator X~.

Sean

Posted 2019-07-19T17:47:09.083

Reputation: 4 136

6

Perl 5, 29 bytes

sub{glob"\Q@_"=~s/v/{v,^}/gr}

Try it online!

My first submission!


Normally, Perl 5 golfers submit programs instead of functions to save from having to include sub{} at a minimum. But they have to add say, say␠, say for or say for␠ in exchange.

By going the sub approach, I could shorten

say for glob"\Q$_"=~s/v/{v,^}/gr        # Perl 5, -0n, 32 bytes

to

sub{glob"\Q@_"=~s/v/{v,^}/gr}           # Perl 5, 29 bytes

The explanation is quite simple. Perl 5 has a builtin glob operator which accepts a shell-like glob pattern which can be used to generate lists of file names (e.g. foo*.txt) or list of strings (e.g. {a,b,c}). The catch is that the newline needs to be escaped, which I've done using quotemeta (as \Q).

ikegami

Posted 2019-07-19T17:47:09.083

Reputation: 193

4

K (ngn/k), 27 25 bytes

{?(,/,/:\:)/x,'"^"/"v"\x}

Try it online!

"^"/"v"\ replace "v" with "^"

x,' zip with the original chars

(,/,/:\:)/ cartesian product over

? uniq

ngn

Posted 2019-07-19T17:47:09.083

Reputation: 11 449

.. and here's me thinking I did alright in 44 bytes! – streetster – 2019-07-20T09:46:57.263

4

APL (Dyalog Classic), 21 17 15 bytes

⊃⊢∘.,.∪'v'⎕r'^'

Try it online!

similar to my k solution

returns an n-dimensional array of strings (n = number of switches)

in easier to explain form: ⊃(∘.,⌿ ⊢ ∪¨ 'v'⎕r'^')

'v'⎕r'^' replace vs with ^s

⊢ ∪¨... unions with each of the original characters. it's a vector of strings of length 1 or 2

∘.,⌿ cartesian product reduction

disclose

to get to the fully golfed version we follow the pattern f⌿ A g¨ B -> A f.g B:

∘.,⌿ ⊢ ∪¨ 'v'⎕r'^' -> ⊢ ∘.,.∪ 'v'⎕r'^'

as a side effect the parentheses are no longer needed

ngn

Posted 2019-07-19T17:47:09.083

Reputation: 11 449

Anything with an outer-product inner product deserves +1. – Adám – 2019-07-21T00:34:39.583

3

Java, 202 197 189 191 bytes

Yes, it's a comparatively verbose language, but that's what I consider as classical golfing:

import java.util.function.Function;

public class SwitchBored
{
    public static void main(String[] args)
    {
        Function<String, String> f = s->{byte i,j,k,m=1,u='^',d='v',a[]=(s+"\n\n").getBytes();for(i=0,s="";i<m;i++,s+=new String(a))for(j=0,k=0;k<a.length;k++){if(a[k]==d||a[k]==u){a[k]=(i&1<<j++)!=0?u:d;m<<=i>0?0:1;}}return s;};

        //System.out.println(f.apply("-v-"));
        System.out.println(f.apply("-v-v-v-\n-v-v-v-"));
        //System.out.println(f.apply("-v-v-v-\n-v-v-"));
        //System.out.println(f.apply("-v-v-v-v-v-\n-v-"));
        //System.out.println(f.apply("-v-v-v-v-v-\n-v-v-v-v-v-"));
    }
}

I thought that a "simple" way of dealing with the line breaks that are necessary to achieve to proper layout was to actually re-use the original input character array, and only fill it with 'v's and '^'s at the appropriate positions.

Updates:

It turned out that not storing the positions allows ditching the int and array variable declarations (at the cost of checking each position of the array whether it contains an v or ^ on the fly), saving 5 bytes.

Another 8 bytes saved by computing the upper limit (1<<numberOfSwitches) more compactly.

According to the rule mentioned in the comment, function declaration should be counted, so now it's a lambda...

Marco13

Posted 2019-07-19T17:47:09.083

Reputation: 1 131

2

I'm pretty sure you have to include the function definition (String generate(String s) {...}) in your byte count. Here's a fixed/lambda version for 191 bytes. I did some minor golfing to shave off 3 bytes

– Benjamin Urquhart – 2019-07-20T02:44:57.713

@BenjaminUrquhart OK, these are details of the "rules" that I'm not familiar with (I'm not golfing here sooo regularly). I thought that the actual { function body } should be relevant, because it does not matter whether you put it into a function that is static or not, and of course, if the declaration counts towards the score, one can convert it into a lambda expression. But that's what is done now, thanks for pointing this out. – Marco13 – 2019-07-20T12:31:46.283

1A few suggestions: 1. use ascii-codes, not chars (d=94). 2. Initialise i when you declare it. 3. Use i++<m instead of separate increment (need to modify the contents of the loop in one place, but this adds no cost). 4. Can you get away with (i&1<<j++)>0? 5. I don't think you need the {} for the inner for loop. 6. You can replace a[k]==d||a[k]==u with a[k]>45, I think. 7. Go with j=k=0. All that should remove 19bytes. – VisualMelon – 2019-07-20T22:27:33.460

@VisualMelon Some of these are the "classical golfing" approaches, and I already applied some of them. Whether or not they are applicable depends - I think that some {} are necessary, but I can have another look. The a[k]>45 may be a neat trick, however. Admittedly, I only wrote this to waste some time waiting for a meeting to start (hence the class name - this was intentional ;-)) but maybe I'll have another look - thanks in any case! – Marco13 – 2019-07-20T22:31:33.520

@Marco13 indeed, they are classic tricks, but all applicable here specifically. I won't spoil the fun by giving you my 172 byte solution based on them (BTW, it think yours is 192, not 191, but I don't know how the lambda counting works: I'm opposed to it in any case). – VisualMelon – 2019-07-20T22:33:35.300

@VisualMelon It's a "contest", in the end - so don't hesitate to post your solution! The 191 came from the comment by Benjamin, and I also wondered whether the final ; should be counted. But let's start nitpicking when we're comparing your 172 solution to a potential 171 one ;-) – Marco13 – 2019-07-20T22:35:58.440

Last couple of hints (I should be asleep...) 8. Changing to s+="\n\n" and removing s="" gives you one of the outputs straight away: you just have to find a way to terminate the loop sooner (left as an exercise). 9. You can save a few bytes by re-computing m every time: added over-head of m=1, but removes the ternary (so you can use m*=2) and means you can remove j completely (replace 1<<j++ with m). Should get you down to 159. (I'm a C#er, I would never post a Java answer! and anyway, nothing I've done is original; it's just golfing your method) – VisualMelon – 2019-07-20T23:18:31.427

@VisualMelon Again, I'm not here sooo regularly, and it has been a while since I've been golfing on that level, so don't hesitate to post your solution (I'm pretty sure that you could have started from scratch and achieved a solution similar to mine, before squeezing even further bytes out of it). – Marco13 – 2019-07-21T09:48:54.180

3

J, 42 bytes

]`('v'I.@e.~[)`[}"1'v^'{~2#:@i.@^1#.e.&'v'

Try it online!

explanation

]`('v' I.@e.~ [)`[}"1 ('v^' {~ 2 #:@i.@^ 1 #. e.&'v')

Let take

-v-
-v-

as our example input.

  • ('v^' {~ 2 #:@i.@^ 1 #. e.&'v') creates all possible combos of just the switches, ignoring the input format. for our example it produces:

    vv
    v^
    ^v
    ^^
    
    • 1 #. e.&'v' counts the numbers of vs in the input.
    • 2 #:@i.@^ raises 2 to that power, produces the integers from 0 to that number i., and converts them to binary #:
    • 'v^' {~ changes to binary digits to v and ^
  • ]`('v' I.@e.~ [)`[}"1 amends the original input, producing one copy of it for each row of the result described in the previous step (ie, all possible v/^ combos). In each copy the v of the original input are replaced with one possible sequence of v/^.

Jonah

Posted 2019-07-19T17:47:09.083

Reputation: 8 729

3

C (gcc), 75 74 70 bytes

-5 byte thanks to @ceilingcat

*b=0;f(char*s){b=b?b:s;*s?f(s+1),*s>46?*s=94,f(s+1),*s='v':0:puts(b);}

Try it online!

requires the memory s points to to be writable

ngn

Posted 2019-07-19T17:47:09.083

Reputation: 11 449

@BrianMinton indeed. and i would never have thought of trying this. nice! – ngn – 2019-07-22T16:57:54.853

3

J, 41 40 24 bytes

[:>@,@{<@(,'^'$~'v'=])"0

Try it online!

ngn

Posted 2019-07-19T17:47:09.083

Reputation: 11 449

very impressive. love the use of {. although i think [:>@,@{<@(,'^'$~'v'=])"0 would be slightly more fair since "Each output board should be of the exact same format as the input" and the input isn't boxed. – Jonah – 2019-07-20T22:48:53.983

@Jonah thanks. corrected. – ngn – 2019-07-20T23:02:08.123

3

Python 2, 87 bytes

def f(s):i=s.find('v');return(i>=0and f(s[:i].replace('^','v')+'^'+s[i+1:])+'\n'or'')+s

Try it online!

A non-regex approach.

Chas Brown

Posted 2019-07-19T17:47:09.083

Reputation: 8 959

A way more concise approach than mine, nice work! – movatica – 2019-07-22T20:49:09.623

3

Python 3.8 (pre-release), 129 117 116 110 106 bytes

-10 bytes thanks to @Chas Brown

f=lambda s:{s.replace('v','{}').format(*['v^'[c<'1']for c in bin(x+i)[::-1]])for i in range(x:=1<<len(s))}

Try it online!

wilkben

Posted 2019-07-19T17:47:09.083

Reputation: 321

1

Welcome to PPCG! 123 bytes using a similar idea.

– Chas Brown – 2019-07-24T00:19:23.120

1119 bytes (previously wrong link in this comment). – Chas Brown – 2019-07-24T01:01:47.267

2

C (gcc), 102 bytes

i,j,l;f(char*s){for(l=j=0;l++<1<<j;puts(""))for(i=j=0;s[i];i++)putchar(s[i]>64?l&1<<j++?118:94:s[i]);}

Try it online!

attinat

Posted 2019-07-19T17:47:09.083

Reputation: 3 495

2

K4, 44 bytes

Solution:

-1{@[x;&w;:;]@'"v^"@a\:'!*/a:(+/w:"v"=x)#2};

Examples:

q)k)-1{@[x;&w;:;]@'"v^"@a\:'!*/a:(+/w:"v"=x)#2}"-v-";
-v-
-^-

q)k)-1{@[x;&w;:;]@'"v^"@a\:'!*/a:(+/w:"v"=x)#2}"-v-\n-v-";
-v-
-v-
-v-
-^-
-^-
-v-
-^-
-^-

q)k)-1{@[x;&w;:;]@/:"v^"@a\:'!*/a:(+/w:"v"=x)#2}"-v-v-\n-v-v-v-\n-v-";
-v-v-
-v-v-v-
-v-
-v-v-
-v-v-v-
-^-
-v-v-
-v-v-^-
-v-
-v-v-
-v-v-^-
-^-
-v-v-
-v-^-v-
-v-
-v-v-
-v-^-v-
-^-
-v-v-
-v-^-^-
-v-
-v-v-
-v-^-^-
-^-
-v-v-
-^-v-v-
-v-
-v-v-
-^-v-v-
-^-
-v-v-
-^-v-^-
-v-
-v-v-
-^-v-^-
-^-
-v-v-
-^-^-v-
-v-
-v-v-
-^-^-v-
-^-
-v-v-
-^-^-^-
-v-
-v-v-
-^-^-^-
-^-
-v-^-
-v-v-v-
-v-
-v-^-
-v-v-v-
-^-
-v-^-
-v-v-^-
-v-
-v-^-
-v-v-^-
-^-
-v-^-
-v-^-v-
-v-
-v-^-
-v-^-v-
-^-
-v-^-
-v-^-^-
-v-
-v-^-
-v-^-^-
-^-
-v-^-
-^-v-v-
-v-
-v-^-
-^-v-v-
-^-
-v-^-
-^-v-^-
-v-
-v-^-
-^-v-^-
-^-
-v-^-
-^-^-v-
-v-
-v-^-
-^-^-v-
-^-
-v-^-
-^-^-^-
-v-
-v-^-
-^-^-^-
-^-
-^-v-
-v-v-v-
-v-
-^-v-
-v-v-v-
-^-
-^-v-
-v-v-^-
-v-
-^-v-
-v-v-^-
-^-
-^-v-
-v-^-v-
-v-
-^-v-
-v-^-v-
-^-
-^-v-
-v-^-^-
-v-
-^-v-
-v-^-^-
-^-
-^-v-
-^-v-v-
-v-
-^-v-
-^-v-v-
-^-
-^-v-
-^-v-^-
-v-
-^-v-
-^-v-^-
-^-
-^-v-
-^-^-v-
-v-
-^-v-
-^-^-v-
-^-
-^-v-
-^-^-^-
-v-
-^-v-
-^-^-^-
-^-
-^-^-
-v-v-v-
-v-
-^-^-
-v-v-v-
-^-
-^-^-
-v-v-^-
-v-
-^-^-
-v-v-^-
-^-
-^-^-
-v-^-v-
-v-
-^-^-
-v-^-v-
-^-
-^-^-
-v-^-^-
-v-
-^-^-
-v-^-^-
-^-
-^-^-
-^-v-v-
-v-
-^-^-
-^-v-v-
-^-
-^-^-
-^-v-^-
-v-
-^-^-
-^-v-^-
-^-
-^-^-
-^-^-v-
-v-
-^-^-
-^-^-v-
-^-
-^-^-
-^-^-^-
-v-
-^-^-
-^-^-^-
-^-

Explanation:

In-place replacement of "^". Determine number of combinations of switches (e.g. 2^n), count up in binary, replace switches...

-1{@[x;&w;:;]@'"v^"@a\:'!*/a:(+/w:"v"=x)#2}; / the solution
-1                                         ; / print to STDOUT, swallow -1
  {                                       }  / lambda taking implicit x
                                        #2   / take 2
                             (         )     / do this together
                                  "v"=x      / does input = "v" ?
                                w:           / save as w
                              +/             / sum up
                           a:                / save as a
                         */                  / product
                        !                    / range 0..n
                    a\:'                     / convert each to base-2
               "v^"@                         / index into "v^"
             @'                              / apply each
   @[x;&w;:;]                                / apply assignment to x at indexes where w is true

streetster

Posted 2019-07-19T17:47:09.083

Reputation: 3 635

2

R, 116 bytes

function(x,u=utf8ToInt(x))apply(expand.grid(rep(list(c(118,94)),sum(u>45))),1,function(i)intToUtf8(`[<-`(u,u>45,i)))

Try it online!

Function returning a vector of newline separated boards

digEmAll

Posted 2019-07-19T17:47:09.083

Reputation: 4 599

ah, I was so focused on taking input in a much harder way that I neglected the ease of this one. Nice use of "[<-"! – Giuseppe – 2019-07-22T17:27:07.933

@Giuseppe: I'm not very satisfied by this solution... but I tried to generate the combinations in other ways (e.g. using binary conversion) but this ended up being the shortest. – digEmAll – 2019-07-23T11:57:11.483

1

JavaScript, 88 bytes

s=>(g=n=>n--?g(n)+`
`+s.replace(/v/g,_=>'v^'[i=n&1,n>>=1,i]):'')(2**~-s.split`v`.length)

Try it online!

darrylyeo

Posted 2019-07-19T17:47:09.083

Reputation: 6 214

1n>>=1 -> n/=2 – ngn – 2019-07-20T10:51:04.290

1

Retina 0.8.2, 29 bytes

T`¶v`;#
+%1`#
v$'¶$`^
%`;|$
¶

Try it online! Explanation:

T`¶v`;#

Change the newlines into ;s and the vs into # markers.

+%1`#

Replace the #s one at a time from left to right.

v$'¶$`^

Change each line into two lines, one with the # replaced with a v, one with it replaced with a ^.

%`;|$
¶

Change the ;s back into newlines and space the results apart.

Neil

Posted 2019-07-19T17:47:09.083

Reputation: 95 035

1

Perl 5 -0, 51 bytes

$_=<>;s/\s/P/g;s/v/{v,^}/g;say s/P|$/\n/gr for glob

Try it online!

Xcali

Posted 2019-07-19T17:47:09.083

Reputation: 7 671

40 (Version1) 40 (Version 2) – ikegami – 2019-07-20T18:56:24.523

39 38 32 29 – ikegami – 2019-07-20T19:07:26.030

1Oh, basic tip: Using -n would have avoided the need for $_=<>; – ikegami – 2019-07-21T11:27:59.210

1

JavaScript (Node.js), 80 73 68 bytes

f=([x,...y],g=c=>f(y).map(z=>c+z))=>x?g(x).concat(x>'a'?g`^`:[]):[y]

Try it online!

ngn

Posted 2019-07-19T17:47:09.083

Reputation: 11 449

1

Python 3 - construct, 203 bytes

def f(a):
 b=[0]
 for l in a.split():b+=[b[-1]+l.count('v')]
 return'\n'.join(''.join(f"{k:b}".zfill(b[-1])[x:y]+'-\n'for x,y in zip(b,b[1:]))for k in range(2**b[-1])).replace('0','-v').replace('1','-^')

Try it online!

First try, not very small but works. There is no elegant string replacement in Python...

The First loop builts a mapping of lines to bit indices, i.e. for each line, the index of the first bit in a bit counter is stored. This is used for indexing the bit counter in the next loop.

The Second loop runs a binary counter, extracts the bits for each line and iteration and joins them. After joining everything together, it is translated back to the switch map format, using string replacement.

I guess, there is a more elegant way by reusing the input string instead of rebuilding it over and over again.

Edit: inspired by the Python 3.8 answer, here is a much shorter replacing version

Python 3 - replace, 123 bytes

def f(a):r=range;n=a.count('v');return'\n'.join(a.replace('v','{}').format(*('v^'[k&2**i>0]for i in r(n)))for k in r(2**n))

Try it online!

movatica

Posted 2019-07-19T17:47:09.083

Reputation: 635

0

Ruby, 64 bytes

Returns an array. Gets numbers from \$1\$ to \$2^v\$ (where \$v\$ is the number of "v" in the input) and flips switches based on the \$v\$ least significant bits. This allows us to save a byte over iterating from \$0\$ to \$2^v-1\$, because the \$v\$ least significant bits in \$2^v\$ are all zero.

In Ruby, i[j] returns the jth bit of i starting from the least significant bit, aka it is equivalent to (i>>j)&1.

->s{(1..2**s.count(?v)).map{|i|j=-1;s.gsub(/v/){'v^'[i[j+=1]]}}}

Try it online!

Value Ink

Posted 2019-07-19T17:47:09.083

Reputation: 10 608

0

Charcoal, 28 bytes

⪫EX²№θv⭆θ⎇⁼λv§v^÷ιX²№…θμv붶

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

   ²                            Literal 2
  X                             Raised to power
    №                           Count of
      v                         Literal `v`
     θ                          In input string
 E                              Map over implicit range
        θ                       Input string
       ⭆                        Map over characters and join
           λ                    Current character
          ⁼                     Equal to
            v                   Literal `v`
         ⎇                      Then
              v^                Literal `v^`
             §                  Circularly indexed by
                 ι              Outer index
                ÷               Integer divided by
                   ²            Literal 2
                  X             Raised to power
                    №           Count of
                        v       Literal `v`
                      θ         In input string
                     …          Truncated to length
                       μ        Inner index
                         λ      Else current character
⪫                         ¶¶    Join with newlines
                                Implicitly print

Neil

Posted 2019-07-19T17:47:09.083

Reputation: 95 035

0

PHP, 93 bytes

for(;$j<1<<$x;$j+=print$s)for($x=0,$s=$argv[1];$i=strpos($s,v,$i+1);$s[$i]=$j&1<<$x++?'^':v);

Try it online!

Standalone program, input via command line.

Loop the number of possible permutations of the input string based on the number of v's. While counting up in binary, replace each binary 1 with a ^ and each binary 0 with a v in the input string.

640KB

Posted 2019-07-19T17:47:09.083

Reputation: 7 149