16
\$\begingroup\$

Task

Given an unsorted list of integers, order it in such a way that the absolute difference of every two adjacent elements will always be equal to 1:

\$|dx| = 1\$

There will be guaranteed one or more solutions. You may choose any one of the solutions as your output. The list's minimal length is 2.

Your task is to output the list in the order that satisfies the condition of this challenge.

Rules

This is code-golf. Standard i/o. Standard loopholes.

Test cases

[1, 2] -> [1, 2] or [2, 1] 
[4, 5, 5, 5, 4] -> [5, 4, 5, 4, 5]
[1, 3, 2, 4, 5] -> [1, 2, 3, 4, 5] or [5, 4, 3, 2, 1]
[3, 0, 1, 1, 2, 4] -> [1, 0, 1, 2, 3, 4] or [4, 3, 2, 1, 0, 1]
[4, 2, 3, 4, 4, 5, 5] -> [2, 3, 4, 5, 4, 5, 4 ] or [4, 5, 4, 5, 4, 3, 2]
[1, 7, 5, 2, 6, 4, 4, 3, 3] -> [1, 2, 3, 4, 3, 4, 5, 6, 7] or the reverse of it
[6,10,2,12,13,5,7,1,14,9,2,1,4,10,13,11,11,12,8,3,9]
-> [11,12,13,14,13,12,11,10,9,10,9,8,7,6,5,4,3,2,1,2,1] or the reverse of it

Link to the Sandbox

\$\endgroup\$
4
  • \$\begingroup\$ There are actually 6 solutions for the last test case. \$\endgroup\$ Commented 2 days ago
  • \$\begingroup\$ @Arnauld it will be ok if you choose any solution \$\endgroup\$ Commented 2 days ago
  • 2
    \$\begingroup\$ This problem can be formulated as finding a Hamiltonian Path in an undirected graph, where each input number forms a node (with duplicates!), and an edge connects two nodes of difference one. The node list of each Hamiltonian Path in traversing order gives a valid solution to the task. \$\endgroup\$ Commented 2 days ago
  • \$\begingroup\$ @movatica I have added tag path-finding \$\endgroup\$ Commented 2 days ago

16 Answers 16

9
\$\begingroup\$

Nekomata + -1, 6 bytes

↕:∆Zƶ¿

Attempt This Online!

↕:∆Zƶ¿
↕           Find a permutation of the input
 :   ¿      Such that
  ∆         The differences between adjacent elements
   Z        Are nonzero
    ƶ       And are small (absolute values <= 1)

The -1 flag outputs the first valid solution.

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

R, 117 116 111 bytes

Edit: -1 byte thanks to Glory2Ukraine.

f=\(x,y={})`if`(any(x|T),unlist(Map(\(i)f(x[-i],c(x[i],y)),which((x-c(y,NA)[1])^2==1|!any(y|T))),F)[1],list(y))

Attempt This Online!

Recursive function that returns the ordered result as a vector in a single-element list.

R has no (built-in) permutations function, so here we gradually build-up the ordered result by starting with each element of x, and trying to prepend elements with an absolute difference of 1 to the first element of the result-so-far.

Ungolfed code:

f=function(x,y={}){             # start with input x 
                                # and empty result-so-far y
    if(length(x)==0) y          # if there's no more x, return the result
    else if(length(y)==0)       # if there's no result-so-far, 
        lapply(seq(x),          #  iterate over each element of x
            function(i)f(x[-i],x[i]))
                                #  putting it into y 
                                #  & recursively calling f with x without this element
    else lapply(which(abs(x-y[1])==1),
                                #  otherwise, iterate over elements of x that 
                                #  have an absolute difference of 1 from the
                                #  first element of y
            function(i)f(x[-i],c(x[i],y)))
                                #  prepending it to y
                                # & recursively calling f with x without this element
}
\$\endgroup\$
2
  • \$\begingroup\$ -1 byte if you replace abs with ^2 \$\endgroup\$ Commented yesterday
  • 1
    \$\begingroup\$ 42 bytes with a randomized approach. \$\endgroup\$ Commented 19 hours ago
5
\$\begingroup\$

Python, 102 101 100 98 bytes

lambda l:min(permutations(l),key=lambda x:{-1,1,*map(int.__sub__,x,x[1:])})
from itertools import*

Attempt This Online!

Intentionally inefficient to save characters; could not complete the final test case in any reasonable length of time (testing 51 quintillion permutations is... technically possible).

Edit 1: Since I had access to all of itertools anyway, I replaced zip(x,x[1:]) with the one character shorter (and faster to boot) pairwise(x).

Edit 2: Shaved one more by dropping pairwise, because subset testing means a single map can do the trick without relying on zip at all.

Edit 3: Shaved two more with pure evil, using the weakly ordered nature of sets and the guarantee that there will be some solution. By making the key a set with -1 and 1 already included, any passing result will have a key of {-1,1}, while non-passing solutions will have a key with at least one additional value. Thus, the passing results will be strict subsets of all non-passing results (which would be ordered with respect to each other only in the most useless ways), and min will return an arbitrary (not random, just dependent on input order) passing result.

Big thanks to Jonathan Allan for the last two improvements.

\$\endgroup\$
4
  • \$\begingroup\$ More evil is 83 bytes :D \$\endgroup\$ Commented yesterday
  • \$\begingroup\$ (again the link makes the comment as long as allowed) ...the list is changed in place using a recursive function that shuffles until it works. \$\endgroup\$ Commented yesterday
  • \$\begingroup\$ @JonathanAllan: Yeah, I considered random, but decided it didn't count if the solution didn't have deterministic behavior. I may need to wait a few million years and hope the hardware holds out, but my solution will definitely find the answer eventually, without exhausting memory, and you could inspect it to figure out how far it's gotten; with random, it might never find a solution. shuffle's own documentation notes that the period of Mersenne Twister means long enough inputs can't actually produce all possible shuffles. \$\endgroup\$ Commented yesterday
  • \$\begingroup\$ Very true, definitely no replacement for what you have! \$\endgroup\$ Commented yesterday
5
\$\begingroup\$

Jelly, 8 bytes

Œ!ạƝE$ƇḢ

Try It Online!

Œ!ạƝE$ƇḢ    main link
Œ!          all permutations
      Ƈ     filter for permutations where
  ạƝ        the absolute differences of each neighboring pair
    E       are all equal
       Ḣ    take the first match

thanks to jonathan allan for this clever observation! because the list can be ordered such that the absolute differences are all \$d = 1\$, then it is impossible to order it such that the absolute differences are all some \$d \neq 1\$ (suppose it is possible; then, there must be two values \$a, b, |a - b| = 1\$, but their difference is the sum of the differences of each pair between them which is a multiple of \$d\$, which is impossible). therefore, if the absolute differences are all equal, they must all be 1

old version

Œ!I*`Ƒ$ƇḢ    main link
Œ!           all permutations
       Ƈ     filter for permutations where
  I          the difference of each neighbor
     Ƒ       is invariant when
   *`        you exponentiate each value by itself (this is only true for ±1)
        Ḣ    take the first such permutation

-1 byte by switching from ạƝ (absolute difference of each pair) to I (difference of each pair) because the *`Ƒ check (x => x == (x ** x)) works for -1 as well

Œ!ạƝỊƑ$ƇḢ also works by checking invariant under ("insignificant" — absolute value less than or equal to 1). this works because any integer above 1 will return 0 for insignificant, and 0 will return 1 which is not equal, so this only works for 1

\$\endgroup\$
2
  • 2
    \$\begingroup\$ You can save a byte using the fact that we know the input can be arranged to a sequence with adjacent differences of one, which in turn means it cannot be rearranged into a sequence where all differences are some \$d \ne 1\$ because there are two elements with a difference of \$1\$ which must be separated by some integer amount of \$\pm d\$s. So, Œ!IAEƊƇḢ. \$\endgroup\$ Commented yesterday
  • \$\begingroup\$ @JonathanAllan ooh good catch, I had thought of using that but I hadn't yet thought over if that would be correct \$\endgroup\$ Commented yesterday
5
\$\begingroup\$

R, 42 bytes

\(a){while(any(diff(a)^2-1))a=sample(a);a}

Attempt This Online!

Randomized. Shuffles the vector randomly until the condition is met. Will usually time out on large inputs.

This comes out much shorter than the deterministic R answer, which currently stands at 111 bytes.

\$\endgroup\$
1
  • \$\begingroup\$ Nice one - I have used basically the same function to solve my testcases. \$\endgroup\$ Commented 16 hours ago
4
\$\begingroup\$

Haskell, 129 bytes

d a(b:bs)|a==b=bs|1<2=b:d a bs;d _ _=[];p[]=[[]];p x=[y:z|y<-x,z<-p(d y x)];f=head.filter((all((1==).abs)).(zipWith(-)<*>tail)).p

Try it online!

Or more nicely formatted:

d a(b:bs)|a==b=bs|1<2=b:d a bs;
d _ _=[];
p[]=[[]];
p x=[y:z|y<-x,z<-p(d y x)];
f=head.filter((all((1==).abs)).(zipWith(-)<*>tail)).p

This does not use functions from the Data.List library, and instead replicates them as follows:

  • d is our List.delete function.
  • p is our List.permutations function.
  • Finally f is main target function.

If we were to import Data.List, we could simply use List.permutations and have an 81 byte solution:

import Data.List;f=head.filter((all((1==).abs)).(zipWith(-)<*>tail)).permutations

This does become very slow as test case length grows as we test all permutations.

New contributor
Luke Sharkey is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
\$\endgroup\$
2
  • 2
    \$\begingroup\$ Nice first answer! You can make your solution accessible online to others and have the bytes counted automatically like this. The imports are generally allowed (it's a matter of taste), but the statement import Data.List has to be added to the solution. \$\endgroup\$ Commented yesterday
  • \$\begingroup\$ Unfortunately p isn't actually equivalent to permutations. It only is for set-like lists (no duplicate elements), which is not given in this setting. \$\endgroup\$ Commented 20 mins ago
3
\$\begingroup\$

Python3, 135 bytes

def f(l):
 q=[([],l)]
 for a,l in q:
  if[]==l:return a
  for i,j in enumerate(l):q+=[(a+[j],l[:i]+l[i+1:])]*([]==a or abs(a[-1]-j)==1)

Try it online!

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

05AB1E, 6 bytes

œ.Δ¥ÄP

Try it online or verify (almost) all test cases. (Test suit omits the last test case, which times out.)

Alternatively, outputting all valid results is 6 bytes as well:

œêʒ¥ÄP

Try it online or verify all test cases. (Test suite times out, even with the omitted large test case.)

Explanation:

œ      # Get all permutations of the (implicit) input-list
 .Δ    # Find the first that's truthy for:
   ¥   #  Get the deltas / forward-differences
    Ä  #  Get the absolute value of each
     P #  Take the product
       #  (note, only 1 is truthy in 05AB1E)
       # (after which the found result is output implicitly)

 ê     # Sort and uniquify this list of permutations
  ʒ    # Filter this list of lists by:
       #  ...
       # (after which all found results are output implicitly)
\$\endgroup\$
2
  • \$\begingroup\$ I don't suppose is any faster than ÄP? \$\endgroup\$ Commented 2 days ago
  • \$\begingroup\$ @Neil Not really. I did try that, as well as üαP, but the difference is marginal. The œ and then iterating over it with either or ʒ is the main bottle-neck here. \$\endgroup\$ Commented yesterday
3
\$\begingroup\$

Google Sheets, 152 bytes

=let(a,tocol(A:A,1),r,rows(a),i,sequence(r),f,lambda(f,a,if(1=r-sum(sort(n(1=abs(filter(a,i<r)-filter(a,i>1))))),a,f(f,sort(a,randarray(r),1)))),f(f,a))

Non-deterministic. Tends to run into the recursion limit with lists of more than eight integers.

screenshot

Prettified:

=let(
  a, tocol(A:A, 1),
  r, rows(a),
  i, sequence(r),
  f, lambda(f, a, if(
    1 = r - sum(sort(n(1 = abs(filter(a, i < r) - filter(a, i > 1))))),
    a, 
    f(f, sort(a, randarray(r), 1))
  )),
  f(f, a)
)
\$\endgroup\$
3
\$\begingroup\$

Vyxal 3, 7 bytes

⧖ʎδ⦷1≊⎋

Vyxal It Online!

⧖ʎδ⦷1≊⎋­⁡​‎‎⁡⁠⁢‏‏​⁡⁠⁡‌⁢​‎‎⁡⁠⁡‏‏​⁡⁠⁡‌⁣​‎‎⁡⁠⁣‏⁠⁠‏​⁡⁠⁡‌⁤​‎‎⁡⁠⁤‏‏​⁡⁠⁡‌⁢⁡​‎‎⁡⁠⁢⁡‏⁠‎⁡⁠⁢⁢‏‏​⁡⁠⁡‌⁢⁢​‎‎⁡⁠⁢⁣‏‏​⁡⁠⁡‌­
 ʎ       # ‎⁡filter...
⧖        # ‎⁢permutations of the input by...
  δ      # ‎⁣are the delta's
   ⦷     # ‎⁤absolute values
    1≊   # ‎⁢⁡all equal to 1?
      ⎋  # ‎⁢⁢close the filter and get head
💎

Created with the help of Luminespire.

<script type="vyxal3">
⧖ʎδ⦷1≊⎋
</script>
<script>
    args=[["[1,2]"],["[4, 5, 5, 5, 4]"],["[1, 3, 2, 4, 5]"],["[3, 0, 1, 1, 2, 4]"],["[4, 2, 3, 4, 4, 5, 5]"],["[1, 7, 5, 2, 6, 4, 4, 3, 3]"]]
</script>
<script src="https://themoonisacheese.github.io/snippeterpreter/snippet.js" type="module"/>

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

Japt -g, 9 bytes

á kÈäa dÉ

Try it

á kÈäa dÉ     :Implicit input of array
á             :Permutations
  k           :Remove elements that return true
   È          :When passed through the following function
    ä         :  Consecutive pairs
     a        :    Reduced by absolute difference
       d      :  Any truthy (not 0)
        É     :    Subtract 1
              :Implicit output of first element
\$\endgroup\$
3
\$\begingroup\$

Charcoal, 37 bytes

⊞υ⟦⟧FυFθF∧¬∧ι⊖↔⁻↨ι⁰κ›№θκ№ικ⊞υ⁺ι⟦κ⟧I⊟υ

Try it online! Link is to verbose version of code. Explanation: Finds all paths in the undirected graph and outputs the last one found which will always be the longest and therefore a solution (assuming one exists).

⊞υ⟦⟧Fυ

Start a depth-first search with a path with no nodes.

Fθ

Loop over each potential node.

F∧¬∧ι⊖↔⁻↨ι⁰κ›№θκ№ικ

If this node is adjacent and it has not already been exhausted, then...

⊞υ⁺ι⟦κ⟧

... add a new path to the search list that includes this node.

I⊟υ

Output the last path found.

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

APL+WIN, 47 bytes

Prompts for vector of integers. Times out for last test case.

s←⎕⋄:while (¯1+⍴s)≠+/1=|-2-/s←s[(⍴s)?⍴s]⋄:end⋄s

Try it online! Thanks to Dyalog Classic APL

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

JavaScript (ES7), 77 bytes

f=o=(a,...b)=>a.map((v,i)=>(v-b[0])**2-1||f(a.filter(_=>i--),v,...b))+a?o:o=b

Try it online!

Commented

f =             // f is a recursive function
o =             // o is the output
(a, ...b) =>    // a[] = input array, b[] = current permutation
a.map((v, i) => // for each value v at index i in a[]:
  (v - b[0])    //   if the squared difference between v and b[0]
  ** 2 - 1 ||   //   is equal to 1:
  f(            //     do a recursive call:
    a.filter(   //       pass a copy of a[]
      _ => i--  //       without the i-th element
    ),          //
    v,          //       prepend v
    ...b        //       to b[]
  )             //     end of recursive call
)               // end of map()
+ a ?           // if a[] was not empty:
  o             //   return o[]
:               // else:
  o = b         //   we have a valid permutation: copy b[] to o[]

JavaScript (ES7), 65 bytes

Non-deterministic version. Likely to stack-overflow on large inputs.

f=a=>a.sort(_=>Math.random()-.5).some(p=v=>(p-(p=v))**2-1)?f(a):a

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ Lack init \$\endgroup\$ Commented 2 days ago
  • \$\begingroup\$ @l4m2 Indeed. Fixed. \$\endgroup\$ Commented 2 days ago
  • \$\begingroup\$ somehow, I knew you would solve it using a recursive method. \$\endgroup\$ Commented 2 days ago
2
\$\begingroup\$

Husk, 7 bytes

ḟoËaẊ-P

Try it online!

ḟoËaẊ-P     # 
ḟ           # Return first value that gives truthy result of
 o          #  function composition: (o f g) x means f (g x)
  Ë         #   Are function results all equal?
   a        #    function = absolute value
    Ẋ       #   Map over pairs of adjacent values
     -      #    subtract
            # applied to 
      P     # List of all permutations of the input
\$\endgroup\$
1
\$\begingroup\$

APL(NARS), 125 chars

f←{⍵≡⍬:⍺⋄⍬≡m←∪⍵/⍨1=∣⍵-⍺[≢⍺]:⍬⋄c←↑m⋄⍬≢r←(⍺,c)∇⍵∼⍦c:r⋄⍬≡m←m∼c:⍬⋄c←↑m⋄(⍺,c)∇⍵∼⍦c}
g←{k←⍵⋄{⍵>≢k:⍬⋄j←,k[⍵]⋄⍬≡v←j f k∼⍦j:∇⍵+1⋄v}1}

// 79+46=125 Program that compile/execute the function: NARS2000 (Win32) Version # 0.5.14.11

They are a couple of recursive function, g function has as input one array of integers, of at last two elements and would return zilde, the void numeric list, if there is no combination of the element of input array such that the difference each contiguos elments of the array result is 1, else it return one combination of element of input array such that the difference each contiguos elements of the array result 1.

f is based on observation that if C is a integer list and y is a integer the set {x in list C: 1=|x-y|} can be have 0, 1 or max 2 element. f build the result one element at time in the alpha argument.

test:

  f←{⍵≡⍬:⍺⋄⍬≡m←∪⍵/⍨1=∣⍵-⍺[≢⍺]:⍬⋄c←↑m⋄⍬≢r←(⍺,c)∇⍵∼⍦c:r⋄⍬≡m←m∼c:⍬⋄c←↑m⋄(⍺,c)∇⍵∼⍦c}
  g←{k←⍵⋄{⍵>≢k:⍬⋄j←,k[⍵]⋄⍬≡v←j f k∼⍦j:∇⍵+1⋄v}1}
  )box on
Was OFF
  g 1 3 4 5 6 
┌0─┐
│ 0│
└~─┘
  g 1,2,3,4
┌4───────┐
│ 1 2 3 4│
└~───────┘
  g 1 2
┌2───┐
│ 1 2│
└~───┘
  g 4 5 5 5 4
┌5─────────┐
│ 5 4 5 4 5│
└~─────────┘
  g 1 3 2 4 5
┌5─────────┐
│ 1 2 3 4 5│
└~─────────┘
  g 3 0 1 1 2 4
┌6───────────┐
│ 1 0 1 2 3 4│
└~───────────┘
  g 4 2 3 4 4 5 5 
┌7─────────────┐
│ 4 5 4 5 4 3 2│
└~─────────────┘
  g 1 7 5 2 6 4 4 3 3 
┌9─────────────────┐
│ 1 2 3 4 3 4 5 6 7│
└~─────────────────┘
  g 6 10 2 12 13 5 7 1 14 9 2 1 4 10 13 11 11 12 8 3 9
┌21─────────────────────────────────────────────────┐
│ 13 14 13 12 11 12 11 10 9 10 9 8 7 6 5 4 3 2 1 2 1│
└~──────────────────────────────────────────────────┘
  x←g 6 10 2 12 13 5 7 1 14 9 2 1 4 10 13 11 11 12 8 3 9
  2{∣⍵-⍺}/x
┌20──────────────────────────────────────┐
│ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1│
└~───────────────────────────────────────┘

so there is at last one other solution for the last array not reported from question post.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.