16
\$\begingroup\$

One lane is closed, the vehicles have to thread their way in according to the zip-lock system: One car from one lane, the next car from the other lane, always taking turns.

Input: Two vehicle queues, represented e.g. as strings, in which short cars are represented by individual symbols, lorries by several identical symbols. The queues may be of different lengths and may even be empty. Symbols may appear more than once. If your language does not support strings, you can also use two lists (see second set of test data) or other forms of input as long as the purpose of the task is not lost.

Output: A vehicle queue in the same representation. The traffic jam is long enough, so at least the source code should be as short as possible!

Test data:

Nzzll,iaaee                   --> Nizzaallee
aabcddddeeeee,1112345555611   --> aa111b2c3dddd4eeeee5555611
foo+bar ooooooooooooooooooooo --> fooooooooooooooooooooooo+bar
feeeuve553iiiiiiiiiii,        --> feeeuve553iiiiiiiiiii
UvtMCaegIYuiet,poeyhllnefoLkI --> UpvoteMyChallengeIfYouLikeIt

Test data for languages that do not support strings:

[1,3,5,7,9,11],[2,4,6,7,7,7,7,7] --> [1,2,3,4,5,6,7,7,7,7,7,7,9,11]
[4,9,9,13,13],[41,41,41,1,11,44] --> [4,41,41,41,9,9,1,13,13,11,44]
[] [2,6,4,3,3,56,8,5,4,3]        --> [2,6,4,3,3,56,8,5,4,3]
\$\endgroup\$
9
  • 1
    \$\begingroup\$ Given that we can take input as lists, I think this is a dup of Zip Uneven Lists. \$\endgroup\$
    – Jonah
    Nov 29, 2023 at 23:43
  • 1
    \$\begingroup\$ Actually I take that back: the spec for Zip Uneven Lists is different. It stops zipping when either list is exhausted. \$\endgroup\$
    – Jonah
    Nov 29, 2023 at 23:54
  • 1
    \$\begingroup\$ "You can also use two lists or other forms of input" What exactly does this mean in terms of the test data? Is Jonah's solution valid? \$\endgroup\$
    – Tbw
    Nov 30, 2023 at 1:50
  • \$\begingroup\$ @Tbw Yes, there is ambiguity. I didn't interpret that to mean we may take lists of vehicles, but rather lists of characters. \$\endgroup\$
    – chunes
    Nov 30, 2023 at 2:07
  • \$\begingroup\$ I am not sure anymore, either, fwiw. \$\endgroup\$
    – Jonah
    Nov 30, 2023 at 3:40

21 Answers 21

9
\$\begingroup\$

Jelly, 3 bytes

ŒgZ

A full program that accepts a pair of the two strings as the first argument and prints the resulting single lane.

Try it online!

How?

ŒgZ - Main Link: pair of lists of characters
Œg  - group runs of equal elements of each
  Z - transpose
    - implicit, smashing print
\$\endgroup\$
6
\$\begingroup\$

Ruby, 33 bytes

f=->a,b{a[/(.)\1*/]?$&+f[b,$']:b}

Try it online!

How it works:

If the first queue is not empty, extract the first vehicle, then exchange the queues, and repeat.

If the first queue is empty, return the whole second queue.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Very clever. Nice work. \$\endgroup\$
    – Jordan
    Nov 30, 2023 at 16:02
4
\$\begingroup\$

Wolfram Language (Mathematica), 26 bytes

Flatten[Split/@#,{2,1,3}]&

Try it online!

Input and output lists of characters.

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

05AB1E, 5 bytes

€γõζS

Input as a pair of strings; output as a list of characters.

Try it online or verify all test cases.

Explanation:

€      # Map over both strings in the (implicit) input-pair:
 γ     #  Split them into equal adjacent groups of substrings
   ζ   # Zip/transpose this list of lists,
  õ    # using an empty string ("") as filler for unequal length lists
    S  # Convert this list of pairs of strings to a flattened list of characters
       # (which is output implicitly as result)
\$\endgroup\$
4
\$\begingroup\$

Uiua, 16 bytes

⊐/⊂♭⍉⬚∘⊟□[]∩⊜□∩.

Try it!

Takes lists of postive integers as input (because this saves a few bytes over strings).

  • ∩. duplicate both inputs

enter image description here

  • ∩⊜□ split both into contiguous equal elements

enter image description here

  • ⬚∘⊟□[] couple lists to matrix, filling with boxed empty list

enter image description here

  • transpose

enter image description here

  • deshape

enter image description here

  • ⊐/⊂ join all

enter image description here

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

Charcoal, 35 bytes

F²⊞υ⪪⮌S¹W∧⌊υ⊟§υ⁰«ι¿⌕⮌§υ⁰ι≔⮌υυ»W⌈υ⊟ι

Try it online! Link is to verbose version of code. Explanation: Seems to be a similar idea to @l4m2's answer, but it just took me that long to think of it after writing my Retina answer that he got there first.

F²⊞υ⪪⮌S¹

Input the two strings, reversing them and splitting them into characters so that they can be processed more easily.

W∧⌊υ⊟§υ⁰«

Until one queue is empty, remove the next character from the first queue, ...

ι

... print it, and...

¿⌕⮌§υ⁰ι

... if the next character in this queue is from a different vehicle, then...

≔⮌υυ

... switch the queues.

»W⌈υ⊟ι

Output the remaining vehicles from the other queue.

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

JavaScript (Node.js), 52 48 bytes

f=([c,...a],b)=>c?[c,...c==a[0]?f(a,b):f(b,a)]:b

Attempt This Online!

Array IO, though inputting string usually work

\$\endgroup\$
1
  • 1
    \$\begingroup\$ I think this fails if the first string is empty. (But I guess you can take lists of characters as input instead.) \$\endgroup\$
    – Arnauld
    Nov 30, 2023 at 8:32
3
\$\begingroup\$

J, 32 bytes

[:;(,/:,&(#\))&(<;.1~2~:/\'_'&,)

Attempt This Online!

The 2nd part of this is the only interesting insight:

  • [:;...&(<;.1~2~:/\'_'&,) This is the preprocessing step that breaks the lists down into the grouped sections. A standard J idiom which is unfortunately a bit verbose. I could save two bytes by using integers instead of strings as input.
  • ,/:,&(#\) The main logic. Since we can't zip uneven lists in J using ,., we just cat the lists , and then sort them /: by 1..n catted with 1..m (where n and m are the two list lengths). This works because sort is stable.
\$\endgroup\$
3
  • 2
    \$\begingroup\$ I think the point of the question is to do the grouping in your answer. \$\endgroup\$
    – Neil
    Nov 30, 2023 at 0:25
  • \$\begingroup\$ @Neil I thought so at first too, but the question states "Of course, you can also use two lists or other forms of input". \$\endgroup\$
    – Jonah
    Nov 30, 2023 at 0:34
  • 1
    \$\begingroup\$ @Neil After reading OPs response I think you are right so I've updated. \$\endgroup\$
    – Jonah
    Nov 30, 2023 at 16:23
3
\$\begingroup\$

C (clang), 61 60 bytes

f(a,b)char*a,*b;{*a?putchar(*a)-*++a?f(b,a):f(a,b):puts(b);}

Try it online!

  • saved 1 Byte thanks to @l4m2
\$\endgroup\$
1
  • \$\begingroup\$ 60 \$\endgroup\$
    – l4m2
    Dec 1, 2023 at 7:45
3
\$\begingroup\$

Perl 5 + -p0, 29 bytes

1while s/^(.)\1*/!print$&/gem

Try it online!

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

Vyxal s, 22 bitsv2, 2.75 bytes

vĠ∩

Try it Online!

Bitstring:

1000110100011111100101

The footer inserts a newline for test case purposes. Port of the jelly answer.

Explained

vĠ∩­⁡​‎‎⁡⁠⁡‏⁠‎⁡⁠⁢‏‏​⁡⁠⁡‌⁢​‎‎⁡⁠⁣‏‏​⁡⁠⁡‌­
vĠ   # ‎⁡Vectorise group-by
  ∩  # ‎⁢Transpose
💎

Created with the help of Luminespire.

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

JavaScript (ES11), 62 bytes

Expects ([str1, str2]).

a=>[...a+a].map((_,i)=>a[i&1].match(/(.)\1*/g)?.[i>>1]).join``

Attempt This Online!

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

Retina 0.8.2, 26 bytes

O$#`.(?<=(\2*(.))+)
$#1
¶

Try it online! Takes input on separate lines but link is to test suite that splits on commas for convenience. Explanation:

O$#`.(?<=(\2*(.))+)
$#1

Sort each character by its vehicle index in its queue. This is a stable sort so that the first vehicle of the first queue sorts first followed by the first vehicle of the second queue etc. The newline is not considered for the sort but it's used by the lookbehind to find the front of the second queue.

The vehicles were sorted without regard for the placement of the newline which is just unnecessary at this point.

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

Noulith, 97 bytes

f:=\a,b->if (a.len<1)b else (c,d:=a.first,a.tail;c$if (d.len>0 and c==d.first)f(d,b)else f(b,d))

Try it online!

Explanation

f:=\a,b ->                  # recursive function
if (a.len<1) b              # return early when first input is empty
else (                      # otherwise
c,d:=a.first,a.tail;        # get first c(h)ar and the rest
c $                         # concat the first c(h)ar with
if (d.len>0 and c==d.first) # if next is a truck
f(d,b)                      # the rest of the truck
else f(b,d))                # otherwise the next lane
\$\endgroup\$
2
\$\begingroup\$

BQN, 12 bytes

∾∾○(+`»⊸≠)⊔∾

Try it online!

Input 𝕨F𝕩. Assumes the leading character isn't a null character.

                            traffic jaaam
           ∾    join        trafficjaaam
          ⊔     group by
    +`»⊸≠        vehicle #s
 ∾○              (joined)   123445612223
                            tj raaa am ff i c
∾               join groups tjraaaamffic

Flattened group-by (∾⊔) is a little shorter than sort-by (⍋⊸⊏).

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

x86-64 machine code, 21 bytes

AA 3A 06 74 03 48 87 D6 AC 84 C0 75 F3 52 5E 3A 06 A4 75 FB C3

Try it online!

Following the standard calling convention for Unix-like systems (from the System V AMD64 ABI), this takes in RDI an address at which to place the result, as a null-terminated byte string, and in RSI and RDX, addresses of the inputs, as null-terminated byte strings. The starting point is after the first 8 bytes.

In assembly, rearranged for easier reading:

f:  lodsb           # Load a byte from address RSI into AL, advancing the pointer.
    test al, al     # Check the value of that byte.
    jnz r           # Jump if it's nonzero.
(This section actually comes first.)
r:  stosb           # Write that byte to the output string, advancing the pointer.
    cmp al, [rsi]   # Compare that byte to the next byte in the string.
    je f            # Jump if they are equal.
    xchg rsi, rdx   # (Otherwise) Swap the pointers (in RSI and RDX).
(From here, continue at the beginning.)
(When the byte is zero, continue to here.)
    push rdx; pop rsi   # Transfer the other pointer from RDX to RSI.
r1: cmp al, [rsi]       # Compare the value at that address to AL, which is 0.
    movsb               # Write the byte from address RSI to the output string,
                        #  advancing both pointers.
    jne r1              # Jump back if the byte was not equal to 0.
    ret                 # Return.
\$\endgroup\$
1
  • \$\begingroup\$ 20 \$\endgroup\$
    – l4m2
    Dec 1, 2023 at 7:35
1
\$\begingroup\$

Go, 133 bytes

func f(a,b string)string{if len(a)<1{return b}
c,a:=a[0],a[1:]
if len(a)>0&&c==a[0]{return string(c)+f(a,b)}
return string(c)+f(b,a)}

Attempt This Online!

Recursive function.

Explanation

func f(a,b string)string{
if len(a)<1{return b}    // return early when first input is empty
c,a:=a[0],a[1:]          // get the current c(h)ar
if len(a)>0&&c==a[0]{    // if the next c(h)ar is the same...
return string(c)+f(a,b)} // recurse to get the truck
return string(c)+f(b,a)} // otherwise move on to the next lane
\$\endgroup\$
1
\$\begingroup\$

Bash, 103 99 bytes

The function. Input is parameters 1 and 2. Output is variable o.

f(){
o=  
while [ "$1$2" ]
do  
c=`expr "$1" : "${1::1}*"`
o+=${1::$c}
set -- "$2" "${1:$c}"
done
}

Try it online!

Uses expr to determine the repeats of the first character, "outputs" the repeats, swaps the strings, and repeats until empty.

Due to limitations in expr, it can't handle characters [, \, or ^, or trailing single parentheses. All of these cause infinite loops, possibly with errors spewing. See the TIO for details.

I could save two characters by removing the quotes on the while statement, but this would make space not be a valid character.

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

Python, 160 159 bytes

from itertools import*
c,g,l=chain.from_iterable,groupby,list;f=lambda a,b:''.join(c(c(zip_longest([l(t)for r,t in g(a)],[l(t)for r,t in g(b)],fillvalue=''))))

Attempt This Online!

Edit 1: removed an extra space

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

Desmos, 96 bytes

C=sgn(L[2...]-L)^2
g(L)=∑_{n=1}^{[1...C.count]}C[n]
f(A,B)=sort(join(A,B),join(0,g(A),0,g(B)))

Ok this can probably be improved somehow but for now this is good enough.

Try It On Desmos!

Try It On Desmos! - Prettified

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

GNU sed -E,  63  59 bytes

The first approach did build a third string behind the two strings to be merged, but it turned out it's cheaper to invest in introducing a mark _ in the first string marking the position where to insert the chars from the second string:

s/^/_/
:1
s/_((.?)\2*)(.*,)((.?)\5*)/\1\4_\3/
/_,/!b1
s///g

The magic mainly takes place in the third line: The ERE (.?)\2* (and the same with 5) match zero or more occurences of the same character (using a backreference, which is not required for ERE by POSIX, but supported by the GNU implementation. Thus, we move those matches in front of the _.

We can't use t for looping, because an empty substitution is always possible, but that's not too expensive, because the addess pattern _, can be reused for removing.

Try it online!

\$\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.