Problem from the "Kvant" magazine. Ball necklace.

Hello friends :slight_smile: . I cannot solve the problem and write code for Arduino.

Task. *Write on the balls the numbers from 1 to 10 so that no sum of two adjacent numbers is divisible by either 3, 5 or 7. *

10! is a relatively small number, so brute force would be my approach.

Sounds like a fun program to write, but far easier using a web based C/C++ interpreter, of which there are a few. Google is your friend here, pick one you like.

I use

it works good.

IOW not an Arduino problem.

a7

I did the brute force attack; took 3 attempts :wink:

I started with
1,3,5,7,4,9,2; left 6, 8, 10. There was a mistake because 5+7 can be divided by 3 :frowning: I saw that one later and maybe the mistake was my luck.
2)
I did put 10 between 1 and 3, 8 between 3 and 5 and 6 between 8 and 5; that's when I noticed above error.
3)
Moved 6 from between 8 and 5 to between 5 and 7 solving the above mistake

Result

01 10 03 08 05 06 07 04 09 02

There are a few distinct patterns; for now I'll leave it up to you to detect them.

But… it’s a necklace. So 2 and 1 are adjacent and sum to 3, divisible by 3.

The necklace arrangement also means fewer than 10! combos, I thought it would be easier to generate and examine 10! and observe that every solution would appear a number of times.

No coffee yet, so…

a7

Ah, sh.t

Now it's going to take me 300 attempts :wink: And failure guaranteed :frowning:

can you do it by hand?
can you capture what you did in code?
are their exceptions to be handled?

Whose exceptions? :wink:

a7

i believe the sequence is is 8 3 5 6 2 9 4 7 10 1, solve by hand with testing using a program

i started with 1 and then sequentially picked the next available value that met the criteria.

when i got the the last digit, 8 was the only choice. so i tried swapping it with other value starting with 1 which happened to work.

it would be interesting to start with any of the 10 values

looks like the brute force approach should fine the reverse sequence above starting with 1. but what if there was no solution staring with 1.

what i meant by exception is that the algorithm above is really two different algorithms, the 2nd being the swapping when the last digit doesn't work.

8 plus 1 equals 9 and can be divided by 3 :wink: Same problem that alto777 pointed out in my sequence. :frowning:

These seem to be the sequences

01 03 08 05 06 02 09 04 07 10
01 07 04 09 02 06 05 08 03 10
01 10 03 08 05 06 02 09 04 07
01 10 07 04 09 02 06 05 08 03
02 06 05 08 03 01 10 07 04 09
02 06 05 08 03 10 01 07 04 09
02 09 04 07 01 10 03 08 05 06
02 09 04 07 10 01 03 08 05 06
03 01 10 07 04 09 02 06 05 08
03 08 05 06 02 09 04 07 01 10
03 08 05 06 02 09 04 07 10 01
03 10 01 07 04 09 02 06 05 08
04 07 01 10 03 08 05 06 02 09
04 07 10 01 03 08 05 06 02 09
04 09 02 06 05 08 03 01 10 07
04 09 02 06 05 08 03 10 01 07
05 06 02 09 04 07 01 10 03 08
05 06 02 09 04 07 10 01 03 08
05 08 03 01 10 07 04 09 02 06
05 08 03 10 01 07 04 09 02 06
06 02 09 04 07 01 10 03 08 05
06 02 09 04 07 10 01 03 08 05
06 05 08 03 01 10 07 04 09 02
06 05 08 03 10 01 07 04 09 02
07 01 10 03 08 05 06 02 09 04
07 04 09 02 06 05 08 03 01 10
07 04 09 02 06 05 08 03 10 01
07 10 01 03 08 05 06 02 09 04
08 03 01 10 07 04 09 02 06 05
08 03 10 01 07 04 09 02 06 05
08 05 06 02 09 04 07 01 10 03
08 05 06 02 09 04 07 10 01 03
09 02 06 05 08 03 01 10 07 04
09 02 06 05 08 03 10 01 07 04
09 04 07 01 10 03 08 05 06 02
09 04 07 10 01 03 08 05 06 02
10 01 03 08 05 06 02 09 04 07
10 01 07 04 09 02 06 05 08 03
10 03 08 05 06 02 09 04 07 01
10 07 04 09 02 06 05 08 03 01

Generated by iterating through all 10! possible combinations on a Windows PC. I do not immediately see a pattern.

you're right, it's a necklace

here's a recursive approach

awk '
# ------------------------------------------------
function disp (n)  {
    for (n = 1; n <= N; n++)
        printf " %2d", pos [n]
    printf "\n"
}

# ------------------------------------------------
function check (a, b)  {
    sum = a + b
    if (! (sum % 3))
        return 1
    if (! (sum % 5))
        return 1
    if (! (sum % 7))
        return 1

  # printf "check: %d %d\n", a, b
    return 0
}

# ------------------------------------------------
function search (p, val, n)  {
    if (used [val])
        return

    if (1 < p)  {
        if (check(pos [p-1], val))
            return
    }

    pos  [p]   = val
    used [val] = 1

    if (N == p)  {
        if (! check(pos [1], pos [N]))  {
            disp()
        }
    }
    else  {
        for (n = 1; n <= N; n++)
            search(p+1, n)
    }

    used [val] = 0
}

# ------------------------------------------------
BEGIN  {
    N = 10
    for (n = 1; n <= N/2; n++)
        search(1,n)
}'

with the following results (after 5, the sequences are just reversed)

 1  3  8  5  6  2  9  4  7 10
  1  7  4  9  2  6  5  8  3 10
  1 10  3  8  5  6  2  9  4  7
  1 10  7  4  9  2  6  5  8  3
  2  6  5  8  3  1 10  7  4  9
  2  6  5  8  3 10  1  7  4  9
  2  9  4  7  1 10  3  8  5  6
  2  9  4  7 10  1  3  8  5  6
  3  1 10  7  4  9  2  6  5  8
  3  8  5  6  2  9  4  7  1 10
  3  8  5  6  2  9  4  7 10  1
  3 10  1  7  4  9  2  6  5  8
  4  7  1 10  3  8  5  6  2  9
  4  7 10  1  3  8  5  6  2  9
  4  9  2  6  5  8  3  1 10  7
  4  9  2  6  5  8  3 10  1  7
  5  6  2  9  4  7  1 10  3  8
  5  6  2  9  4  7 10  1  3  8
  5  8  3  1 10  7  4  9  2  6
  5  8  3 10  1  7  4  9  2  6

It's a necklace!

Your results "normalized" and sorted:

1 3 8 5 6 2 9 4 7 10
1 3 8 5 6 2 9 4 7 10 
1 3 8 5 6 2 9 4 7 10 
1 3 8 5 6 2 9 4 7 10 
1 3 8 5 6 2 9 4 7 10 
1 7 4 9 2 6 5 8 3 10
1 7 4 9 2 6 5 8 3 10
1 7 4 9 2 6 5 8 3 10 
1 7 4 9 2 6 5 8 3 10 
1 7 4 9 2 6 5 8 3 10 
1 10 3 8 5 6 2 9 4 7
1 10 3 8 5 6 2 9 4 7 
1 10 3 8 5 6 2 9 4 7 
1 10 3 8 5 6 2 9 4 7 
1 10 3 8 5 6 2 9 4 7 
1 10 7 4 9 2 6 5 8 3
1 10 7 4 9 2 6 5 8 3
1 10 7 4 9 2 6 5 8 3 
1 10 7 4 9 2 6 5 8 3 
1 10 7 4 9 2 6 5 8 3

Further @gcjr About those exceptions, it didn't land: I was teasing you about their != there...

a7

looks like there are just 4 unique sequences

  1  3  8  5  6  2  9  4  7 10
  1  7  4  9  2  6  5  8  3 10
  1 10  3  8  5  6  2  9  4  7
  1 10  7  4  9  2  6  5  8  3

i normalized and then unique sorted (sort -u) ster's data and found the same 4 unique sequences.

therefore, there's no need to test each possible value when starting, cases 2-10 can be skipped. this reduces the # of recursive calls from 32,775 to 6701. (btw, 10! is 3.6M)

thinking about corner (exceptions) and redundant (pruning) cases is important in algorithm design. just curious.

[color=#202124]Share the finished code :) [/color]

i posted an awk program implementing a recursive algorithm in post #10

Read up on permutations; you will have over 3 million possible combinations with 10 numbers.

Next find something on the web that is able to generate all permutations and modify it so it will display only if it matches the criteria. I'm not a mathematics person, so that is what I did.

First with Windows C++ using next_permutation. As I suspect that that will not work too well with Arduino, I searched for a C solution and found Write a program to print all Permutations of given String - GeeksforGeeks. Modified it to be able to handle an array of 4 numbers instead of a c-string, once that was verified went for 10 numbers and lastly added the criteria. This was all running on the PC.

Next I modified the printfs in the original code to use Serial.print so it could be used with Arduino and that was it.

Code on a PC takes 2 seconds to find the matching permutations, on an Arduino 6 minutes.

@sterretje "Code on a PC takes 2 seconds to find the matching permutations, on an Arduino 6 minutes."

Is that your PC from 15 years ago? :wink:

I wasn't gonna do it, but did. A naive brute force method involving pieces of code, which pieces took me longer to find in my mess that it did to cobble together, solved it in 1 second.

I'm not sure my code will run on the Arduino. I am sure I will be unable to keep from trying.

Same with a few optimisations, but nothing like "cheating" where we use inspection too much to cut it, e.g., from 10! to 9!, a nice win but deviates from the true brutality of brute force.

EDIT: the first two optmisations made it run slower, so I am giving up. Obvsly modern desktop machines are bringing things to the table that are better left to the compiler writers and hardware engineers.

a7

the awk code i posted earlier takes 0.109/0.046/0.076 sec real/user/sys time
(2.66 gHz i7)

the code that only searches starting with 1 takes 0.094/0.030/0.015 sec

the code would be faster is the test for a valid pair (not divisible by 3/5/7) were pre-computed in a 2d matrix to avoid the math and just do a table lookup

alto777:
Is that your PC from 15 years ago? :wink:

Not that old, but probably 8-10 years old. I3-2120 @ 3.3GHz, 8GB memory.

Friends. Found a solution to the problem, a C ++ code. Who will translate to Arduino?

code