28
\$\begingroup\$

Consider two lists, A and B. To weave them together, we take the first element of A, then the first element of B, then the next element of A, the next element of B, and so on, ending with the last element of A.

A = [1,2,3,4,5]
B = [6,7,8,9]
A weave B = [1,6,2,7,3,8,4,9,5]

This process works as described if A is exactly one element longer than B. If B is too short, we pad it to the required length by repeating its values cyclically:

A = [1,2,3,4,5]
B = [7,8]
A weave B = [1,7,2,8,3,7,4,8,5]

Similarly, if A is too short, we repeat its values cyclically:

A = [1,2]
B = [6,7,8,9]
A weave B = [1,6,2,7,1,8,2,9,1]

Note: the output must always begin and end with an element of A. If A and B are the same length, A is too short and must be cycled:

A = [1,2,3]
B = [7,8,9]
A weave B = [1,7,2,8,3,9,1]

I'm using the term "weave" for this operation instead of the more common "interleave," because the cycling and the requirement to end with the first list make it different from normal interleaving. This challenge was inspired by Emulate Jelly's tie-scan, which conceptually amounts to weaving a list of integers with a list of functions.

Challenge

Given two nonempty lists of positive integers, weave them together and output/return the result.

You may take the second list first if you prefer. If you do, please say so in your solution.

This is ; the goal is to minimize the size of your code, measured in bytes.

Test cases

[1] [2] -> [1,2,1]
[1,1] [2] -> [1,2,1]
[1,2,3] [6] -> [1,6,2,6,3]
[6] [1,2,3] -> [6,1,6,2,6,3,6]
[10,10] [42,42] -> [10,42,10,42,10]
[5,5] [5,5,5] -> [5,5,5,5,5,5,5]
[1,2,3,4,5] [6,7,8,9] -> [1,6,2,7,3,8,4,9,5]
[1,2,3,4,5] [7,8] -> [1,7,2,8,3,7,4,8,5]
[1,2] [6,7,8,9] -> [1,6,2,7,1,8,2,9,1]
[1,2,3] [7,8,9] -> [1,7,2,8,3,9,1]

Here's a reference implementation in Python.

\$\endgroup\$
3
  • \$\begingroup\$ Related; related. \$\endgroup\$
    – DLosc
    Commented Apr 22 at 17:12
  • \$\begingroup\$ When will the output terminate? As long as both list run to the last? \$\endgroup\$
    – tsh
    Commented Apr 23 at 9:42
  • 1
    \$\begingroup\$ @tsh It depends on which list is longer; see the examples for the different possibilities. Summarized in one sentence: the output ends when the full contents of both lists have been output and the final element is an element of the first list. \$\endgroup\$
    – DLosc
    Commented Apr 23 at 18:03

23 Answers 23

11
\$\begingroup\$

R, 61 60 57 54 50 bytes

Edit: -1 byte thanks to @Giuseppe, -3 bytes thanks to int 21h -- Glory to Ukraine -- and again -4 bytes thanks to @Giuseppe.

\(A,B,`?`=length)rep(rbind(A,B),,max(?A,1+?B)*2-1)

Attempt This Online!


Modification of the above answer that takes the input as a list of two vectors - credit of @Giuseppe and int 21h -- Glory to Ukraine --:

R, 49 bytes

\(L)rep(Reduce(rbind,L),,max(lengths(L)+0:1)*2-1)

Attempt This Online!

\$\endgroup\$
11
  • 5
    \$\begingroup\$ 60 bytes - I almost had this but didn't realize you could rep A only so was a fair bit longer. \$\endgroup\$
    – Giuseppe
    Commented Apr 22 at 20:18
  • 5
    \$\begingroup\$ Maybe like this 54 bytes golf? Though the output is vertical but it seems it does not contradict the rules. \$\endgroup\$ Commented Apr 25 at 8:14
  • 3
    \$\begingroup\$ @Giuseppe that escalated quickly :) \$\endgroup\$
    – pajonk
    Commented Apr 25 at 11:57
  • 5
    \$\begingroup\$ Fun alternate 50 bytes with a different input format (list of vectors) \$\endgroup\$
    – Giuseppe
    Commented Apr 25 at 13:21
  • 5
    \$\begingroup\$ @Giuseppe reduce 1 byte with Reduce! \$\endgroup\$ Commented Apr 25 at 13:30
8
\$\begingroup\$

Vyxal, 9 bytes

@÷›∴vẎƒYṪ

Try it Online!

    vẎ    # Extend each to length
   ∴      # Maximum of
@÷        # len(a)    
@ ›       # And len(b)+1
      ƒY  # Interleave
        Ṫ # Remove trailing element of b
\$\endgroup\$
7
\$\begingroup\$

Python, 63 bytes

lambda a,b:sum(zip(a*(i:=max(len(a),len(b)+1)*2-1),b*i),())[:i]

Attempt This Online!

\$\endgroup\$
7
+500
\$\begingroup\$

Acc!!, 424 ... 294 286 bytes

Count n while 1 {
_+N%8*8^n
Count i while 0^(_/8^n) {
_*n^n^2
Count i while n-i {
_+_/n^n^2/8^i%2*n^(_/n^n%n*n+_/n^(_/n^n%n)%n+2)+0^(_/n^n^2/8^i%2)*n^(_/n^n%n)+_/n^n^2/8^i%4/2*n^n
}
Count i while (_%n*2-2-i)/_+(_/n%n*2-i)/_+2 {
Write 49)*(_/n^(i/2%(_/n^(i%2)%n)+i%2*n+2)%n
Write 9
}
}
}

Try it online!

Accepts two arrays, formatted as comma-separated unary values with the arrays separated by a newline. Outputs a tab-separated unary array and terminates with an error.

Commented

# Format of accumulator:
#   input:
#     + buffer
#   parsing:
#     + buffer*n^n^2
#     + b[0]*n^(n+2) + b[1]*n^(n+3) + b[3]*n^(n+4) + ...
#     + arr_select*n^n
#     + a[0]*n^2     + a[1]*n^3     + a[2]*n^4     + ...
#     + len(b)*n
#     + len(a)
#
# n = len(buffer)                     # includes '\n' for both lines
# buffer = base-8 encoding of input   # least significant digit represents first char ('\n' -> 2, ',' -> 4, '1' -> 1)
#
# Useful Facts:
#   - a[i] < n       (due to unary input)
#   - b[i] < n       (due to unary input)
#   - len(a) < n - 2
#   - len(b) < n - 2
#
# Useful Snippets:
#   - len(a)         ->  _%n
#   - len(b)         ->  _/n%n
#   - a[i]           ->  _/n^(i+2)%n
#   - b[i]           ->  _/n^(n+i+2)%n
#   - buffer[i]      ->  _/n^n^2/8^i%8
#   - arr_select     ->  _/n^n%n

Count n while 1 {  # for n in [0, 1, 2, 3, ...]:
  _+N%8*8^n  # buffer.append(getchar()%8)

  Count i while 0^(_/8^n) {  # if buffer[n] == '\0':
    _*n^n^2  # convert accumulator to parsing type
    # arr_select is initially a

    Count i while n-i {  # for i in [0, 1, 2, ..., n - 1]:
      # _
      # + _/n^n^2/8^i%2 * n^(_/n^n%n*n+_/n^(_/n^n%n)%n+2)   # arr[len(arr)] += 1 if buffer[i] == '1'
      # + 0^(_/n^n^2/8^i%2) * n^(_/n^n%n)                   # len(arr) += 1 if buffer[i] != '1'
      # + _/n^n^2/8^i%4/2 * n^n                             # switch arr_select if buffer[i] == '\n'
      _+_/n^n^2/8^i%2*n^(_/n^n%n*n+_/n^(_/n^n%n)%n+2)+0^(_/n^n^2/8^i%2)*n^(_/n^n%n)+_/n^n^2/8^i%4/2*n^n
    }

    # Output
    Count i while (_%n*2-2-i)/_+(_/n%n*2-i)/_+2 {     # for i in [0, 1, 2, ...] while i <= len(a)*2-2 or i <= len(b)*2:
      Write 49)*(_/n^(i/2%(_/n^(i%2)%n)+i%2*n+2)%n    # | output arr[i/2%len(arr)] in unary (arr refers to a or b based on i%2)
      Write 9                                         # | output '\t'
    }
  }
}
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Using the size of the input as an upper bound is a really clever way to handle arbitrarily long lists of arbitrarily big numbers! Bounty incoming. \$\endgroup\$
    – DLosc
    Commented Apr 25 at 3:43
6
\$\begingroup\$

Uiua 0.11.0, 19 bytes SBCS

↘¯1♭⍉⊟∩↯⟜:¤+⊃↥≥∩⧻,,

Try on Uiua Pad!

Takes two lists on stack and outputs the interleaved list.

Explanation

,,  # dup both on stack
∩⧻  # get both lengths
⊃↥≥ # max length & test len(b) >= len(a)
¤+  # add together and enclose in list
⟜:  # insert it third on stack
∩↯  # reshape both to that length, cycling
⊟   # join lists as two rows
⍉   # transpose the matrix
♭   # flatten matrix
↘¯1 # drop the last element

(equivalently, +⊃↥≥ could be replaced with ↥+1: to get max(len(a), len(b)+1) like in other solutions)

\$\endgroup\$
6
\$\begingroup\$

JavaScript (ES6), 63 bytes

f=(a,b,i=0,j)=>a[i]|b[j]|i/j?[a[i%a.length],...f(b,a,j,i+1)]:[]

Try it online!

Commented

f = (              // f is a recursive function taking:
  a,               //   a[] = first array
  b,               //   b[] = second array
  i = 0,           //   i = pointer in a[], initialized to 0
  j                //   j = pointer in b[], initially undefined
) =>               //
a[i] |             // if a[i] is defined
b[j] |             // or b[j] is defined
i / j ?            // or i = j, meaning that we're currently
                   // processing the array which was originally
  [                // passed as the first one:
    a[             //   append the next entry from a[],
      i % a.length //   using i modulo the length of a[]
    ],             //   followed by the result of
    ...f(          //   a recursive call:
      b, a,        //     with a[] and b[] exchanged
      j, i + 1     //     i = j and j = i + 1
    )              //   end of recursive call
  ]                //
:                  // else:
  []               //   stop
\$\endgroup\$
5
\$\begingroup\$

Perl 5 -a, 65 bytes

@a||(@a=@F)}{do{say$a[$i%@a]}while($i<$#a||$i<@F)&&say$F[$i++%@F]

Try it online!

Input on two lines, numbers space separated.

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

Charcoal, 17 bytes

IE⊖⊗⌈Eθ⁺Lιꧧθι⊘ι

Try it online! Link is to verbose version of code. Takes input as a list of lists. Explanation:

      θ             Input list of lists
     E              Map over lists
         ι          Current list
        L           Length
       ⁺            Plus
          κ         Current index
    ⌈               Take the maximum
   ⊗                Doubled
  ⊖                 Decremented
 E                  Map over implicit range
             θ      Input list of lists
            §       Cyclically indexed by
              ι     Current value
           §        Cyclically indexed by
                ι   Current value
               ⊘    Halved
I                   Cast to string
                    Implicitly output each element on its own line
\$\endgroup\$
5
\$\begingroup\$

05AB1E, 11 bytes

εgN+}àδ∍ø˜¨

Input as a pair of lists.

Try it online or verify all test cases.

Explanation:

ε        # Map over the lists of the (implicit) input-pair
 g       #  Pop and push the length
  N+     #  Add the 0-based map-index
}à       # After the map: pop and push the maximum of len(a) and len(b)+1
  δ      # Map over the lists of the (implicit) input-pair again,
         # using this maximum as argument:
   ∍     #  Extend the lists to this size
    ø    # Then zip/transpose; swapping rows/columns
     ˜   # Flatten it
      ¨  # Remove the last element
         # (after which the result is output implicitly)

Notes:

  1. εgN+} has some equal-bytes alternatives, like €gā<+ or €g.āO
  2. 05AB1E does have an interweave builtin (), but using zip/transpose + flatten (ø˜) is 1 byte shorter than pushing the two lists separately to the stack and interleaving them (`).
\$\endgroup\$
5
\$\begingroup\$

Jelly,  12  11 bytes

-1 thanks to emanresu A (Just add one to the length of B rather than looking at the sort order of the lengths; for some reason, I had thought that failed in an edge-case.)

ṁ€Ẉ+Ø.ṀƊZFṖ

A monadic Link that accepts the pair of lists and yields a list.

Try it online! Or see the test-suite.

How?

ṁ€Ẉ+Ø.ṀƊZFṖ - Link: pair of lists, [A, B]                    e.g.  ab wxyz
       Ɗ    - last three links as a monad - f([A, B]):
  Ẉ         -   length of each -> [len(A), len(B)]                 [2, 4]
   +Ø.      -   add [0,1] -> [len(A), len(B)+1]                    [2, 5]
      Ṁ     -   maximum -> max(len(A), len(B)+1)                   5
ṁ€          - mould each of {[A, B]} like {[1..that]}              ababa wxyzw
        Z   - transpose                                            aw bx ay bz aw
         F  - flatten                                              awbxaybzaw
          Ṗ - remove rightmost                                     awbxaybza
\$\endgroup\$
2
  • \$\begingroup\$ 11 (I think?) (actually disregard that but maybe there's some trick you can do with +Ø.) \$\endgroup\$
    – emanresu A
    Commented Apr 23 at 2:44
  • \$\begingroup\$ My first thought was to add [0,1], but I thought it failed for some edge-case. The only change to your suggestion is reordering to allow a quickchain to work. \$\endgroup\$ Commented Apr 23 at 11:45
5
\$\begingroup\$

Haskell, 58 bytes

(a:c)?l=a:l?(c++[a])
a!b=take(sum(max(2<$a)$2<$0:b)-1)$a?b

Attempt This Online!

Golfed version of the 74-byter thanks to @xnor.

2 <$ a creates a list of 2s whose length is that of a, and max chooses the longer list. Extremely cool way to avoid the repeated length.

Haskell, 60 bytes

f 0
l=length
f n(a:c)b=a:f(1-n)b(c++[a|l c+n<l b])
f _ a _=a

Attempt This Online!

Same algorithm as the 67-byte version, but swaps around the two lists on each iteration. n controls when to extend the shorter list:

  • A B : We want A to be 1 longer than B; extend if tail of A is strictly shorter than B; n = 0
  • B A' : We want B to be of equal length to A'; extend if tail of B is at least 2 shorter than B; n = 1

Haskell, 67 bytes

l=length
(a:c)!(b:d)=a:b:(c++[a|l c<=l d])!(d++[b|l c>l d+1])
a!_=a

Attempt This Online!

Keeps cycling the shorter one until the remaining lengths agree (i.e. the first is exactly 1 longer than the second).

Haskell, 74 bytes

l=length
(a:c)?(b:d)=a:b:c?d
a!b=take(max(l a-1)(l b)*2+1)$cycle a?cycle b

Attempt This Online!

Interleaves two infinitely cycled lists and takes a prefix of appropriate length.

\$\endgroup\$
2
  • \$\begingroup\$ Here's 63 bytes from your 74, maybe with some more improvements it can win out \$\endgroup\$
    – xnor
    Commented Apr 24 at 5:44
  • \$\begingroup\$ 58 bytes \$\endgroup\$
    – xnor
    Commented Apr 24 at 9:01
4
\$\begingroup\$

Vyxal, 82 bitsv2, 10.25 bytes

@₌ÞṠG+vẎ÷YṪ

Try it Online!

Bitstring:

0101010011101001110001001000010001101100111010101110100101000001100010011000011010
\$\endgroup\$
2
  • \$\begingroup\$ ... this doesn't even work for the linked test case... \$\endgroup\$
    – Neil
    Commented Apr 23 at 0:05
  • \$\begingroup\$ @Neil that was because I misunderstood the question. It's fixed now \$\endgroup\$
    – lyxal
    Commented Apr 23 at 0:18
4
\$\begingroup\$

JavaScript (Node.js), 66 bytes

f=(a,b,i=0,j=0)=>[a[j%a.length],...b[j]||a[j+!i]?f(b,a,!i,j+i):'']

Try it online!

JavaScript (Node.js), 68 bytes

f=(a,b,i=0,j=i>>1)=>[a[j%a.length],...b[j]||a[j-~i%2]?f(b,a,i+1):'']

Try it online!

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

J, 22 bytes

[:}:@,@,./(>.>:)&#$&>;

Try it online!

If A is left arg and B right:

Extends each list to the max of [A, B+1], zips, and flattens, removes last.

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

APL+WIN, 31 22 bytes

Prompts for A and B as a nested vector

¯1↓,⍉⊃(⌈/0 1+⍴¨n)⍴¨n←⎕

Try it online! Thanks to Dyalog Classic

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

Ruby, 61 59 bytes

->a,b{(a*w=2*[b.size,a.size-1].max).zip(b*w).flatten[0..w]}

Try it online!

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

Haskell, 53 bytes

a?b=max(init$a!cycle b)$cycle a!b
(h:p)!q=h:q!p
e!_=e

Try it online!

Based on ideas from Bubbler's solutions. The recursive helper function ! takes elements alternating from two lists until it goes past the end of one of the lists. The main function ? tries first endlessly cycle'ing one of the two lists before calling !, and outputs the longer of the two outcomes.

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

C (gcc), 139 88 (ceilingcat) bytes

ceilingcat golfed this the rest of the way:

d,l,i;w(a,b,c,p,q)int*a,*b,*c;{for(i=d=l=-1;i++<p-(p>q)<<1;)c[i]=i%2?b[++d%q]:a[++l%p];}

old:

#define s p>q?2*p-1:2*q+1
#define E int*
void w(E a,E b,E c,int p,int q){int d=-1,l=-1,h=s;for(int i=0;i<h;++i)c[i]=i%2?b[++d%q]:a[++l%p];}

Try it online!

ungolfed function:

void weave(int* a /*outer array*/,int* b /*inner array*/,int* c /*result array*/,int p /*size of a*/,int q /*size of b*/)
{
     if (p>q) s = 2*p-1; //if a/b is longer, size and # of loops 
     else s = 2*q+1;     //is double (if a, last element belongs to a, -1)
                         // (opposite for b)  
     int d=-1 /*current index of b*/,l=-1 /*current index of a*/,h=s /*temp for #define*/;
     for (int i=0;i<h;++i) 
          if (i%2 /*every other digit change arrays*/) 
               c[i]=b[++d%q]; /*odd numbers take next from b*/
          else c[i]=a[++l%p];/*even numbers take next from a*/
}
\$\endgroup\$
2
  • \$\begingroup\$ Welcome to CGCC, and nice first answer! \$\endgroup\$
    – DLosc
    Commented Apr 27 at 23:19
  • \$\begingroup\$ @ceilingcat thanks, edited in your answer. what a way to learn things about a language! \$\endgroup\$
    – INT3
    Commented Apr 28 at 11:50
2
\$\begingroup\$

Nekomata, 14 bytes

ᵐ#:x+Ṁ$ᵒ%ᵐᶻ@ji

Attempt This Online!

Much longer than solutions in other golfing languages, because Nekomata doesn't have a built-in for extending or molding a list.

Takes input as a list of two lists.

ᵐ#:x+Ṁ$ᵒ%ᵐᶻ@ji      Takes [[1,2,3],[6]] as an example
ᵐ#              Length of each element
                    [[1,2,3],[6]] -> [3,1]
  :             Duplicate
                    [3,1] -> [3,1] [3,1]
   x+           Add [0,1]
                    [3,1] [3,1] -> [3,1] [3,2]
     Ṁ          Maximum
                    [3,1] [3,2] -> [3,1] 3
      $         Swap
                    [3,1] 3 -> 3 [3,1]
       ᵒ%       Outer product with modulo
                    3 [3,1] -> [[0,0],[1,0],[2,0]]
         ᵐᶻ@    For each element, zip with the original list and take the nth element
                    [[1,2,3],[6]] [[0,0],[1,0],[2,0]] ->  [[1,6],[2,6],[3,6]]
            j   Join
                    [[1,6],[2,6],[3,6]] -> [1,6,2,6,3,6]
             i  Remove the last element
                    [1,6,2,6,3,6] -> [1,6,2,6,3]
\$\endgroup\$
2
\$\begingroup\$

Pip -xp, 17 bytes

HWV:_H M[#aU#b]Mg

Attempt This Online!

Explanation

HWV:_H M[#aU#b]Mg
               Mg  ; Map this function to each list:
        [     ]    ;  Make a list containing:
         #a        ;   Length of first program argument list
           U#b     ;   One plus length of second program argument list
       M           ;  Get its maximum
    _H             ;  Take that many elements from function argument list, cycling
 WV:               ; Interleave the resulting two lists
H                  ; Remove the last element

(Yes, Pip's interleave builtin is called "weave". No, it doesn't mean what this challenge means by "weave"--although I am thinking of adding a new builtin that does.)

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

Scala 3, 155 154 144 bytes

Saved 1 byte thanks to @DLosc

Saved 10 bytes thanks to @corvus_192


Golfed version. Attempt This Online!

(a,b)=>(if(b.size<a.size){a zip g(b)}else{g(a)zip(b:+0)}).flatMap(t=>Seq(t._1,t._2)).toList.init
def g(a:Seq[Int])=Stream.continually(a).flatten

Ungolfed version. Attempt This Online!

object Main {
  def weave(a: List[Int], b: List[Int]): List[Int] = {
    val z = if (b.length < a.length) {
      a.zip(Stream.continually(b).flatten)
    } else {
      Stream.continually(a).flatten.zip(b ++ List(0))
    }
    val newTuple = z.flatMap(t => List(t._1, t._2)) // flatten the tuples
    // println(s"newTuple = $newTuple")
    newTuple.dropRight(1).toList
  }

  def main(args: Array[String]): Unit = {
    val testCases = List(
      (List(1), List(2), List(1, 2, 1)),
      (List(1, 1), List(2), List(1, 2, 1)),
      (List(1, 2, 3), List(6), List(1, 6, 2, 6, 3)),
      (List(6), List(1, 2, 3), List(6, 1, 6, 2, 6, 3, 6)),
      (List(10, 10), List(42, 42), List(10, 42, 10, 42, 10)),
      (List(5, 5), List(5, 5, 5), List(5, 5, 5, 5, 5, 5, 5)),
      (List(1, 2, 3, 4, 5), List(6, 7, 8, 9), List(1, 6, 2, 7, 3, 8, 4, 9, 5)),
      (List(1, 2, 3, 4, 5), List(7, 8), List(1, 7, 2, 8, 3, 7, 4, 8, 5)),
      (List(1, 2), List(6, 7, 8, 9), List(1, 6, 2, 7, 1, 8, 2, 9, 1)),
      (List(1, 2, 3), List(7, 8, 9), List(1, 7, 2, 8, 3, 9, 1))
    )

    testCases.foreach { case (a, b, expected) =>
      val result = weave(a, b)
      println(s"$a, $b => $result")
      assert(result == expected)
    }
  }
}
\$\endgroup\$
1
  • \$\begingroup\$ 136 bytes: a=>b=>(if(b.size<a.size){a zip g(b)}else{g(a)zip(b:+0)}).flatMap(t=>Seq(t._1,t._2)).init def g(a:Seq[Int])=Stream.continually(a).flatten \$\endgroup\$
    – corvus_192
    Commented Apr 24 at 10:19
1
\$\begingroup\$

PowerShell Core, 138 bytes

for($a,$b=$args;$i-($l=(($m=$a.Count),($n=$b.Count)|sort)[-1])){$a[$i%$m]
$s=$i-ne$m-1-or$m-ne$l-or$i-eq$n-1
,$b[$i++%$n]*$s},$a[$i%$m]*$s

Try it online!

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

Desmos, 109 bytes

a=A.length
b=B.length
i=[2...2max(a,b+1)]
k=floor(i/2)-1
f(A,B)=\{\mod(i,2)=0:A[\mod(k,a)+1],B[\mod(k,b)+1]\}

Try It On Desmos!

Try It On Desmos! - Prettified

Due to their similarities, I tried to separate out A[\mod(k,a)+1] and B[\mod(k,b)+1] into one function, but that ended up being a bit longer than just writing both out in full.

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