g | x | w | all
Bytes Lang Time Link
nanRust240831T124135Z138 Aspe
052JavaScript Node.js240827T011728Zl4m2
594Oracle SQL 11.2240828T151244ZJeto
127Clojure240903T135900ZNikoNyrh
109C gcc240831T014044ZConsindi
114C clang240828T135743Zjdt
117Scala 3240831T021730Z138 Aspe
011Brachylog240829T094440ZFatalize
066R240827T191400ZDavid Jo
009Japt240827T064722ZShaggy
049Ruby240827T170409ZJordan
064Python 3240827T175843ZJonathan
071Python240826T215815Zshape wa
00605AB1E240827T071746ZKevin Cr
026Retina240827T104206ZNeil
1087Jelly240827T001136ZJonathan
154Google Sheets240826T231658Zdoubleun
069JavaScript ES6240826T210254ZArnauld
009Vyxal240826T212519Zemanresu
018Charcoal240826T210607ZNeil
023Jelly240826T191846Zhyperneu

Rust, 316 312 294 286 278 bytes

Saved 4+18+8+8=38 bytes thanks to @ceilingcat


Golfed version. Attempt This Online!

fn f<T:Clone>(x:&[T])->Vec<T>{let r:Vec<T>=(0..).zip(x).flat_map(|(i,b)|{x.iter().take(i).map(move|a|(a.clone(),b.clone()))}).into_iter().flat_map(|(a,b)|vec![a.clone(),a,b.clone(),b]).collect();let z=r.len()-1;let mut y=vec![r[z].clone()];y.extend(r.iter().take(z).cloned());y}

Ungolfed version. Attempt This Online!

fn two_element_combinations<T: Clone>(list: &[T]) -> Vec<(T, T)> {
    list.iter()
        .enumerate()
        .flat_map(|(i, b)| {
            list.iter()
                .take(i)
                .map(move |a| (a.clone(), b.clone()))
        })
        .collect()
}

fn f<T: Clone>(list: &[T]) -> Vec<T> {
    let result: Vec<T> = two_element_combinations(list)
        .into_iter()
        .flat_map(|(a, b)| vec![a.clone(), a, b.clone(), b])
        .collect();
    
    let mut rotated = Vec::with_capacity(result.len());
    rotated.push(result[result.len() - 1].clone());
    rotated.extend(result.iter().take(result.len() - 1).cloned());
    rotated
}

fn main() {
    let result = f(&['a', 'b', 'c', 'd']);
    println!("{:?}", result);
}

JavaScript (Node.js), 52 bytes

or 56 bytes if not flatten

f=([a,...x])=>x.flatMap(t=>[a,t,...f(x),t,...x=[a]])

Try it online!

or 67 bytes flatten

JavaScript (Node.js), 71 bytes

f=([a,b,...x],y)=>b?[[a,b],...y||f([b,...x]),[b,a],...f([a,...x],[])]:x

Try it online!

Oracle SQL 11.2, 594 bytes

WITH v(s,i,j,r)AS(SELECT :1,1,LENGTH(:1),''FROM DUAL UNION ALL SELECT s,i+DECODE(j,i+1,1,0),DECODE(j,i+1,LENGTH(s),j-1),SUBSTR(s,i,1)||SUBSTR(s,j,1)FROM v WHERE j>i),l AS(SELECT i,j,r,1 p FROM v UNION ALL SELECT i,j,REVERSE(r),2 p FROM v),m AS(SELECT l.*,DECODE(p,1,0,DECODE(LAG(i,2,i)OVER(ORDER BY i,j DESC,p),i,0,j-i))o FROM l)SELECT LISTAGG(r)WITHIN GROUP(ORDER BY o,i,j DESC,p)FROM m;

Un-golfed

WITH v(s,i,j,r) AS --> Generate the pairs
(
  SELECT :1 s
       , 1 i
       , LENGTH(:1) j
       , '' r
  FROM DUAL
  UNION ALL
  SELECT s
       , i+DECODE(j,i+1,1,0)
       , DECODE(j,i+1,LENGTH(s),j-1)
       , SUBSTR(s,i,1)||SUBSTR(s,j,1)
  FROM v
  WHERE j>i
)
, l AS  --> Add the reverse pairs
(
  SELECT i,j,r,1 p
  FROM v
  UNION ALL
  SELECT i,j,REVERSE(r),2 p FROM v
)
, m AS  --> Add a new variable to order the pairs based on when the first item in the pair change 
(
  SELECT l.*
       , DECODE(p,1,0,DECODE(LAG(i,2,i)OVER(ORDER BY i,j DESC,p),i,0,j-i))o
  FROM l
  WHERE r IS NOT NULL
)
SELECT LISTAGG(r)WITHIN GROUP(ORDER BY o,i,j DESC,p)
FROM m
;

Clojure, 127 bytes

#(first(filter(fn[i](=(set(map(fn[[x a][b y]](= a b))i(rest i)))#{true}))(iterate shuffle(for[a % b % :when(not= a b)][a b]))))

This turned out to be a bit... exotic. The list of greetings is shuffled until it satisfies the condition! So the runtime will be poor on larger groups of people. Is this O(n!) ?

Ungolfed with thread-last macro:

(def perm #(->> (for [a %
                      b %
                      :when (not= a b)]
                  [a b])
                (iterate shuffle)
                (filter (fn [i] (->> (map = (map second i)
                                            (map first (rest i)))
                                     set
                                     (= #{true}))))
                first))

TIO.

C (gcc), 109 bytes

n;main(c,s)char**s;{for(n=c;s[n]||(++s)[n=1];n++)printf("%s %s %s %s ",*s,s[n],s[n],s[!s[n+1]*(n-1?1:3-c)]);}

Try it online!

C (clang), 115 114 bytes

f(**s,n,*o){for(int*w,j=n-1,i=*o=0;i<n;i-=i-j&&!strstr(o,w)?j=i-!strcat(o,w):-1)asprintf(&w,"%s %s\n",s[j],s[i]);}

Try it online!

Ungolfed:

void func(char **s, int n, char *out) {
    int i = 0;
    int j = n - 1;
    char pair[80];
    *out = 0;
    for (; i < n; i++) {
        if (i != j) {
            sprintf(pair, "%s %s\n", s[j], s[i]);
            if (!strstr(out, pair)) {
                strcat(out, pair);
                j = i;
                i = -1;
            } 
        }
    }
}

Scala 3, 117 bytes

Golfed version. Attempt This Online!

L=>{val r=L.zipWithIndex.flatMap{case(b,i)=>L.take(i).map(a=>(a,b))}.flatMap{case(a,b)=>Seq(a,a,b,b)};r.last+:r.init}

Ungolfed version. Attempt This Online!

object Main {
  def twoElementCombinations[T](L: List[T]): Seq[(T, T)] = {
    L.zipWithIndex.flatMap { case (b, i) =>
      L.take(i).map(a => (a, b))
    }
  }

  def f[T](L: List[T]): Seq[T] = {
    val result = twoElementCombinations(L).flatMap { case (a, b) => Seq(a, a, b, b) }
    val rotated = result.last +: result.init
    rotated
  }

  def main(args: Array[String]): Unit = {
    println(f(List('a', 'b', 'c', 'd')))
  }
}

Brachylog, 11 bytes

{⊇Ċ}ᶠcgj↺ᵗz

Try it online!

Explanation

Same algorithm as most approaches.

{⊇Ċ}ᶠ          Find all pairs
     cgj       Flatten and duplicate
        ↺ᵗ     Shift duplicate cyclically to the left
           z   Zip

A more declarative approach, 18 bytes

{⊇Ċp}ᶠp.¬{s₂tʰhᵗ≠}

Try it online!

Explanation

Longer and less efficient, but easily readable.

{⊇Ċp}ᶠ                Find all pairs, both permutations
      p.              The final output is a permutation of this list of all pairs
        ¬{       }    Such that it is impossible…
          s₂          To find two consecutive pairs…
            tʰ         Where the last element of the first pair…
              hᵗ≠      Is different from the first element of the second pair

R, 66 bytes

This accepts a character vector of names x that needs to be specified beforehand:

for(i in 1:ncol(combn(x,2)))print(combinat::permn(combn(x,2)[,i]))

Japt, 11 9 bytes

à2 c
íUéJ

Try it

à2 c\níUéJ     :Implicit input of array U
à2             :Combinations of length 2
   c           :Flatten
    \n         :Reassign to U
      í        :Interleave with
       Ué      :  U rotated right
         J     :    -1 times (i.e., rotated left)

Ruby, 49 bytes

Port of Jonathan Allan's Jelly answer; give him an upvote.

->a{(b=[*a.combination(2)].flatten).zip b.rotate}

Attempt This Online!

Python 3, 64 bytes

I started by looking at shape warrior t's excellent Python 3 answer (go upvote!), but got to a slightly different solution in terms of both function and form, so went with a new post.

f=lambda h,*r:r and sum(((h,h,n,n)for n in r),r[-1:])[:-1]+f(*r)

A recursive function that accepts the names as arguments and returns a flat tuple of the names.

Try it online!

How?

f=lambda     :                                                   # f is a function
          ,                                                      # that accepts:
         h                                                       #   h, the head name
           *r                                                    #   r, the rest of the names
              r and                                              # return r if empty, else...
                    sum(                     ,      )            # concatenate:
                                              r[-1:]             #   the tail name
                        (         for n in r)                    #   and for each n(ame) in r:
                         (h,h,n,n)                               #     (head, head, n, n)
                                                     [:-1]       # and remove the very last n
                                                          +      # and concatenate
                                                           f(  ) #   a recursive call to f
                                                             *r  #     with just the rest
                                                                 #       (i.e. h will be the
                                                                 #        first of the rest)

Python, 88 74 71 bytes

lambda L:sum([[a,a,b,b]for b in L for a in L[:L.index(b)]],L[-1:])[:-1]

Attempt This Online!

-14 bytes thanks to att, replacing a call to itertools.combinations. -3 bytes thanks to Jonathan Allan with a better way to get the iteration index. Outputs as a flattened list.

Ungolfed algorithm:

from collections import deque

def two_element_combinations(L):
    for i, b in enumerate(L):
        # In the golfed code: i == L.index(b) as names are unique
        for a in L[:i]:
            yield a, b

def f(L):
    result = deque(x for a, b in two_element_combinations(L) for x in [a, a, b, b])
    result.rotate()  # a b c d -> d a b c
    return result

Explanation

If we imagine a directed graph where vertices represent friends and edges represent introductions, this challenge algorithmically boils down to finding an Eulerian path in a complete digraph.

It turns out that (using example vertices A, B, C, D, E, F) the loop with the sequence of vertices
ABACBCADBDCDAEBECEDEAFBFCFDFEF is a valid Eulerian path. Grouping the vertices (which gives the edges that appear at even-numbered positions under 0-indexing), we have
AB AC BC AD BD CD AE BE CE DE AF BF CF DF EF, the two-element combinations of ABCDEF where the first element comes before the second. Rotating left by one yields
BACBCADBDCDAEBECEDEAFBFCFDFEFA, and regrouping (which gives the edges that appear at odd-numbered positions under 0-indexing) gives us
BA CB CA DB DC DA EB EC ED EA FB FC FD FE FA, the two-element combinations of ABCDEF where the first element comes after the second (in a slightly weird order -- combinations that end in A are moved to the end of their respective groups). Between these two groupings, every edge is accounted for exactly once in the entire path.

The output format in this challenge requires a sequence of edges, not vertices. The loop with vertices A B C D has the edges AB BC CD DA, or equivalently DA AB BC CD. The flattened form DAABBCCD can be produced from ABCD by doubling each vertex and rotating right by one.

In the actual code, we take the first list of two-element combinations, double both vertices in each combination, and then flatten and rotate the entire thing. For vertices A, B, C, D, the golfed code calculates rotate_right(flatten([AABB, AACC, ..., CCDD])) as
all_but_last(D + AABB + AACC + ... + CCDD).

05AB1E, 7 6 bytes

.ƘDÀø

Port of @JonathanAllan's Jelly answer, so make sure to upvote that answer as well!
-1 byte thanks to @JonathanAllan

Try it online or verify all test cases.

Explanation:

        #  e.g. input = [1,2,3]
.Æ      # Create all possible pairs of the (implicit) input-list
        #  STACK: [[1,2],[1,3],[2,3]]
  ˜     # Flatten it
        #  STACK: [1,2,1,3,2,3]
   D    # Duplicate this list
        #  STACK: [1,2,1,3,2,3],[1,2,1,3,2,3]
    À   # Rotate the items in the copy once towards the left
        #  STACK: [1,2,1,3,2,3],[2,1,3,2,3,1]
     ø  # Zip to create pairs using both lists
        #  STACK: [[1,2],[2,1],[1,3],[3,2],[2,3],[3,1]]
        # (after which the result is output implicitly)

Retina, 26 bytes

w`(.).*(.)
$1$1$2$2
V`.+\B

Try it online! Link includes test cases. Explanation:

w`(.).*(.)
$1$1$2$2

List all pairs of characters without replacement, but doubled.

V`.+\B

Mirror all but the last character of the string.

33 bytes to output using the order from A097285:

rw`(.).*(.)
$1$1$2$2
(.)(.+)
$2$1

Jelly,  10 8  7 bytes

ŒcẎṙ-żƊ

A monadic Link that accepts a list of names (lists of characters) and yields a list of pairs of names.

Try it online!

How?

ŒcẎṙ-żƊ - Link: Names
Œc      - ordered pairs {Names} -> [[a,b],[a,c],...,[a,Z],[b,c],...[Y,Z]]
  Ẏ     - tighten               -> [a,b,a,c,...,a,Z,b,c,...,X,Y,Z]
      Ɗ - last three links as a monad - f(X=that):
    -   -   -1
   ṙ    -   rotate {X} left by -1 (rotate right by 1)
                                -> [Z,a,b,a,c,...,a,Z,b,c,...,X,Y]
     ż  -   zip with {X}        -> [[Z,a],[a,b],[b,a],[a,c],...,[a,Z],[Z,b],[b,c],...,[X,Y]]

Google Sheets, 154 bytes

=let(s," ",f,lambda(f,a,let(n,counta(a)-1,h,+a,t,choosecols(a,sequence(n,1,2)),if(n,join(s,sort(h&s&h&s&t&s&t),f(f,t)),))),mid(f(f,1:1),2+len(A1),9^9)&A1)

Put the names in row 1 and the formula in cell A2.

The formula takes the first name and pairs it with every name that follows it, repeating each name twice every time. Does the same recursively with remaining names, pairing each name with every name that follows it (but without pairing with preceding ones.) Finally, tidies up the head and tail with string manipulation.

screenshot

Ungolfed:

=let( 
  s, " ", 
  f, lambda(f, a, let( 
    n, counta(a) - 1, 
    head, single(a), 
    tail, choosecols(a, sequence(n, 1, 2)), 
    if(n, 
      join(s, 
        sort(head & s & head & s & tail & s & tail), 
        f(f, tail) 
      ), 
      "" 
    ) 
  )), 
  mid(f(f, { A1:1 }), 2 + len(A1), 9^9) & A1 
)

Uses sort() as array enabler only.

Pretty much the same in JavaScript (non-competing):

f = a =>
  a.slice(1)
    .map(n => ([a[0], a[0], n, n]).join())
    .join()
  + (a.length > 1 ? ',' + f(a.slice(1)) : '')

g = A => f(A).slice(A[0].length + 1) + A[0]

console.log(g(["Alice","Bob","Cole","Dave"])) // "Alice,Bob,Bob,Alice,Alice,Cole,Cole,Alice,Alice,Dave,Dave,Bob,Bob,Cole,Cole,Bob,Bob,Dave,Dave,Cole,Cole,Dave,Dave,Alice"

JavaScript (ES6), 69 bytes

Expects an array of strings and returns a flat list as a comma-separated string.

f=([v,...a],b=v)=>a.map((p,i)=>[v,p,p,a[i+1]?v:i?[a[0],f(a,b)]:b])+""

Try it online!

Method

Given \$n\$ elements, we do \$n-1\$ iterations from \$j=0\$ to \$j=n-2\$.

At each iteration, we generate:

With five elements, this gives:

$$\begin{aligned}&j=0:\color{blue}{(0,1)}\color{green}{(1,0)}\color{blue}{(0,2)}\color{green}{(2,0)}\color{blue}{(0,3)}\color{green}{(3,0)}\color{blue}{(0,4)}\color{purple}{(4,1)}\\ &j=1:\color{blue}{(1,2)}\color{green}{(2,1)}\color{blue}{(1,3)}\color{green}{(3,1)}\color{blue}{(1,4)}\color{purple}{(4,2)}\\ &j=2:\color{blue}{(2,3)}\color{green}{(3,2)}\color{blue}{(2,4)}\color{purple}{(4,3)}\\ &j=3:\color{blue}{(3,4)}\color{red}{(4,0)}\end{aligned}$$

Note that the actual JS implementation directly manipulates the entries of the original array rather than their indices.

Commented

f = (             // f is a recursive function taking:
  [ v,            //   v   = next element
       ...a ],    //   a[] = remaining elements
  b = v           //   b   = copy of the first element
) =>              //
a.map((p, i) =>   // for each element p at index i in a[]:
  [               //
    v, p,         //   insert the pair (v, p)
    p,            //   insert the pair (p, X), where ...
    a[i + 1] ?    //     if this is not the last element:
      v           //       X = v
    :             //     else:
      i ?         //       if i > 0:
        [ a[0],   //         X = a[0] followed by the result
          f(a, b) //             of a recursive call
        ]         //
      :           //       else (last iteration):
        b         //         X = b
  ]               //
)                 // end of map()
+ ""              // coerce to a string

Vyxal, 9 bytes

KƛZṫwẊ;fǓ

Try it Online! Port of Neil's Charcoal answer.

Kƛ    ;   # Over every prefix  
  Z       # Double each value
    wẊ    # Append the last value to
   ṫ      # The rest
       fǓ # Flatten and move the first character to the end.

Vyxal, 14 bytes

₌ẊZFṖvf'zy∩≈;h

Try it Online!

Brute force answer. 12 bytes by removing the ;h if we can output all solutions.

    Ṗ          # Permutations
 Ẋ             # Of all pairs in the input
₌ ZF           # Aside from doubles of one item
     vf        # Flatten each
       '    ;h # Find one where
        zy     # Every other overlapping pair
          ∩≈   # Has all elements equal?

Charcoal, 18 bytes

Φ⭆θ⭆…θκ⁺ײλײικ§θ⁰

Try it online! Link is to verbose version of code. Explanation: A097285 is almost the sequence of indices, with each element doubled, except that there is only one of the first element at the start, the second coming at the end.

  θ                 Input list
 ⭆                  Map over letters and join
     θ              Input list
    …               Truncated to length
      κ             Current index
   ⭆                Map over letters and join
          λ         Inner letter
        ײ          Doubled
       ⁺            Concatenated with
             ι      Outer letter
           ײ       Doubled
Φ             κ§θ⁰  Remove the first element and append it to the end

Jelly, 23 bytes

2œṖ$ÐƤṖUp/€żUẎṖƲ€Ẏ;Uṡ2Ɗ

Try It Online!

pretty horribly long but it is fairly efficient and i kinda like the idea of it which is basically this: starting from the first person counting forwards, we introduce them to everyone starting from the last person counting backwards and do this back and forth until the next person, then we do not introduce them back, and we repeat this until we've done all of the introductions except each person to the one before them which we do at the end to close the loop

Explanation

2œṖ$ÐƤṖUp/€żUẎṖƲ€Ẏ;Uṡ2Ɗ    main link
    ÐƤ                     for each suffix of the list
2œṖ$                       - partition at index 2, so split the first element off
      Ṗ                    remove the last element (the single list)
       U                   reverse (vectorizing) to flip the targets around
           €               for each of these pairs
         p/                - take their cartesian product to get each intro pair
                Ʋ€          for each of these lists of intros
           żU              - interleave with the reverse
             Ẏ             - flatten by one level
              Ṗ            - remove the last element (the last back-intro)
                 Ẏ         flatten by one level
                  ;   Ɗ    append
                   Uṡ2     - each pair of [the original list reversed]