Cover a set with multiples

14

Lets take a set of integers greater than 1 and call it X. We will define S(i) to be the set of all members of X divisible by i where i > 1. Would like to choose from these subsets a group of sets such that

  • Their union is the set X

  • No element of X is in two of the sets.

For example we can regroup {3..11} as

      {3,4,5,6,7,8,9,10,11}
S(3): {3,    6,    9,     }
S(4): {  4,      8,       }
S(5): {    5,        10,  }
S(7): {        7,         }
S(11):{                 11}

Some sets cannot be expressed in this way. For example if we take {3..12}, 12 is a multiple of both 3 and 4 preventing our sets from being mutually exclusive.

Some sets can be expressed in multiple ways, for example {4..8} can be represented as

      {4,5,6,7,8}
S(4): {4,      8}
S(5): {  5,     }
S(6): {    6,   }
S(7): {      7, }

but it can also be represented as

      {4,5,6,7,8}
S(2): {4,  6,  8}
S(5): {  5,     }
S(7): {      7, }

Task

Our goal is to write a program that will take a set as input and output the smallest number of subsets that cover it in this fashion. If there are none you should output some value other than a positive integer (for example 0).

This is a question so answers will be scored in bytes, with less bytes being better.

Tests

{3..11}       -> 5
{4..8}        -> 3
{22,24,26,30} -> 1
{5}           -> 1

Post Rock Garf Hunter

Posted 2017-07-15T16:07:41.280

Reputation: 55 382

If there are none you should output some value other than a positive integer (for example 0). Can't our program result in undefined behaviour instead? – Mr. Xcoder – 2017-07-15T16:13:05.237

Also, can you add a test case like [5..5]? Can we receive things like [8..4]? – Mr. Xcoder – 2017-07-15T16:14:20.820

@Mr.Xcoder No it may not. Programs should be able to identify impossible cases not just loop forever or crash on them. – Post Rock Garf Hunter – 2017-07-15T16:14:28.110

1"12 is a multiple of both 3 and 4 preventing our sets from being mutually exclusive": why? I don't see anything else in the problem statement which requires 12 to go into both subsets. – Peter Taylor – 2017-07-15T16:14:54.603

@Mr.Xcoder I added [5] I don't know what [8..4] is supposed to mean. – Post Rock Garf Hunter – 2017-07-15T16:15:27.550

@WheatWizard [8..4] means [8,7,6,5,4] – Mr. Xcoder – 2017-07-15T16:15:47.163

@PeterTaylor It is required to go in those sets. I'll try to work that in. – Post Rock Garf Hunter – 2017-07-15T16:16:10.330

1Also, what's with the test cases? [22,24,26,30] are all multiples of 2. Are you sure it wouldn't be better to delete this and sandbox it? – Peter Taylor – 2017-07-15T16:16:30.703

@Mr.Xcoder Thats the same as [4,5,6,7,8], sets do not have order – Post Rock Garf Hunter – 2017-07-15T16:16:34.333

@PeterTaylor that should have said one, I must've hit the wrong key when I was copying it over – Post Rock Garf Hunter – 2017-07-15T16:17:59.803

@PeterTaylor Does that clarify why we can't add 12? The wording is very tricky. – Post Rock Garf Hunter – 2017-07-15T16:22:52.130

Parameterised names ftw. "We can define the subset S(i) as the set of elements of X which are divisible by i". – Peter Taylor – 2017-07-15T16:37:47.943

Add more test cases please.. – J42161217 – 2017-07-15T17:45:15.250

Ah, also needs to require the divisor to be greater than 1. – Peter Taylor – 2017-07-15T19:01:22.913

Is it even possible to have no solution? – Zacharý – 2017-07-15T21:44:12.690

@Zacharý The example [3..12] has no solution as explained. – Post Rock Garf Hunter – 2017-07-15T21:57:31.603

Answers

6

Python 2, 167 bytes

lambda a:([q for q in range(a[-1])if a in[sorted(sum(j,[]))for j in combinations([[p for p in a if p%i<1]for i in range(2,1+a[-1])],q)]]+[0])[0]
from itertools import*

Try it online!

-9 bytes thanks to Zacharý
-4 bytes thanks to Mr. Xcoder
-2 bytes by using lists instead of sets
-5 bytes by using a in [...] rather than any([a == ...]).
-2 bytes thanks to Mr. Xcoder
-8 bytes by merging statements
-5 bytes thanks to Mr. Xcoder
-7 bytes thanks to Mr. Xcoder / Zacharý
+7 bytes to fix bug
-1 byte thanks to ovs

note

This is extremely slow for larger maximum numbers because it is in no way optimized; it did not within 2 minutes on Mr. Xcoder's device for [22, 24, 26, 30].

HyperNeutrino

Posted 2017-07-15T16:07:41.280

Reputation: 26 575

5

Clingo, 51 bytes

{s(2..X)}:-x(X).:-x(X),{s(I):X\I=0}!=1.:~s(I).[1,I]

Demo

$ echo 'x(3..11).' | clingo cover.lp -
clingo version 5.1.0
Reading from cover.lp ...
Solving...
Answer: 1
x(3) x(4) x(5) x(6) x(7) x(8) x(9) x(10) x(11) s(3) s(4) s(5) s(7) s(11)
Optimization: 5
OPTIMUM FOUND

Models       : 1
  Optimum    : yes
Optimization : 5
Calls        : 1
Time         : 0.003s (Solving: 0.00s 1st Model: 0.00s Unsat: 0.00s)
CPU Time     : 0.010s
$ echo 'x(4..8).' | clingo cover.lp -
clingo version 5.1.0
Reading from cover.lp ...
Solving...
Answer: 1
x(4) x(5) x(6) x(7) x(8) s(3) s(4) s(5) s(7)
Optimization: 4
Answer: 2
x(4) x(5) x(6) x(7) x(8) s(2) s(5) s(7)
Optimization: 3
OPTIMUM FOUND

Models       : 2
  Optimum    : yes
Optimization : 3
Calls        : 1
Time         : 0.001s (Solving: 0.00s 1st Model: 0.00s Unsat: 0.00s)
CPU Time     : 0.000s
$ echo 'x(22;24;26;30).' | clingo cover.lp -
clingo version 5.1.0
Reading from cover.lp ...
Solving...
Answer: 1
x(22) x(24) x(26) x(30) s(5) s(8) s(22) s(26)
Optimization: 4
Answer: 2
x(22) x(24) x(26) x(30) s(3) s(22) s(26)
Optimization: 3
Answer: 3
x(22) x(24) x(26) x(30) s(2)
Optimization: 1
OPTIMUM FOUND

Models       : 3
  Optimum    : yes
Optimization : 1
Calls        : 1
Time         : 0.004s (Solving: 0.00s 1st Model: 0.00s Unsat: 0.00s)
CPU Time     : 0.000s
$ echo 'x(5).' | clingo cover.lp -
clingo version 5.1.0
Reading from cover.lp ...
Solving...
Answer: 1
x(5) s(5)
Optimization: 1
OPTIMUM FOUND

Models       : 1
  Optimum    : yes
Optimization : 1
Calls        : 1
Time         : 0.001s (Solving: 0.00s 1st Model: 0.00s Unsat: 0.00s)
CPU Time     : 0.000s

Anders Kaseorg

Posted 2017-07-15T16:07:41.280

Reputation: 29 242

This seems to not detect cases without solutions like x(3..12). (or do I need to update?). BTW, can you suggest a good introduction to clingo? – Christian Sievers – 2017-07-17T12:03:04.580

1

@ChristianSievers Oops, that was a bug, which I’ve now fixed. It should output UNSATISFIABLE in such a case. I mostly used the Potassco guide.

– Anders Kaseorg – 2017-07-17T12:12:21.323

4

Mathematica, 105 bytes

Length@Select[Subsets@Table[Select[s,Mod[#,i]==0&],{i,2,Max[s=#]}],Sort@Flatten@#==Sort@s&][[1]]~Check~0&


Try it online
copy and paste the code with ctrl+v,
paste the input at the end of the code,
hit shift+enter to run

input

[{3,4,5,6,7,8,9,10,11}]

takes a list as input
outputs 0 if there are none

J42161217

Posted 2017-07-15T16:07:41.280

Reputation: 15 931

Nice use of Check – Keyu Gan – 2017-07-16T02:27:26.320

Why didn't you undelete your first answer once you had a working version? – Neil – 2017-07-16T15:41:22.833

Because this was a totally new approach? Is there a problem? – J42161217 – 2017-07-16T15:43:11.553

4

Haskell, 136 bytes

import Data.List
f l|m<-maximum l=(sort[n|(n,c)<-[(length s,[i|j<-s,i<-[j,2*j..m],elem i l])|s<-subsequences[2..m]],c\\l==l\\c]++[0])!!0

Try it online!

How it works

f l     =                           -- input set is l
   |m<-maximum l                    -- bind m to maximum of l
       [   |s<-subsequences[2..m]]  -- for all subsequences s of [2..m]
        (length s, )                -- make a pair where the first element is the length of s
            [i|j<-s,i<-[j,2*j..m],elem i l]
                                    -- and the second element all multiples of the numbers of s that are also in l
     [n|(n,c)<-       ,c\\l==l\\c]  -- for all such pairs (n,c), keep the n when c has the same elements as l, i.e. each element exactly once
   sort[ ]++[0]                     -- sort those n and append a 0 (if there's no match, the list of n is empty)
 (     )!!0                         -- pick the first element

Take a lot of time for {22,24,26,30}.

nimi

Posted 2017-07-15T16:07:41.280

Reputation: 34 639

3

Jelly, 38 35 34 33 31 28 25 24 23 20 19 bytes

ṀḊŒPð%þ@⁹¬Sḟ1ðÐḟL€Ḣ

-5 bytes thanks to Leaky Nun

Try it online!

I think the third test case works, but it is very slow. 0 is outputted when there are no solutions.

Explanation (might have gotten this explanation wrong):

ṀḊŒPð%þ@⁹¬Sḟ1ðÐḟL€Ḣ     (input z)
ṀḊ                      - 2 .. max(z)
  ŒP                    - powerset
    ð                   - new dyadic chain
     %þ@⁹               - modulo table of z and that
         ¬              - logical not
          S             - sum
           ḟ1           - filter out 1's
             ðÐḟ        - filter out elements that satisfy that condition
                L€      - length of each element
                  Ḣ     - first element

Zacharý

Posted 2017-07-15T16:07:41.280

Reputation: 5 710

118 bytes – Leaky Nun – 2017-07-16T12:53:17.350

Thanks! And thank you for not submitting that yourself! – Zacharý – 2017-07-16T13:26:32.230

I've got a different 18 byte solution closer to my original, I personal like this one better: ṀḊŒPðḍ@þ@⁹Sḟ1ðÐḟḢL – Zacharý – 2017-07-16T13:29:07.530

Woah... ṀḊ actually is a really cool trick! – Zacharý – 2017-07-16T13:30:35.120

Whoops, that doesn't work, and neither does my rewrite! This should output 0, not 1

– Zacharý – 2017-07-16T13:48:15.377

There, I fixed your solution at the cost of two bytes. – Zacharý – 2017-07-16T14:24:40.267

You can use L€Ḣ instead of Ḣḟ0L. – Leaky Nun – 2017-07-16T16:19:31.730

2

Julia, 91 bytes

x->(t=[];for i in x z=findfirst(x->x==0,i%(2:maximum(x)));z∈t?1:push!(t,z) end;length(t))

Tanj

Posted 2017-07-15T16:07:41.280

Reputation: 199

Um ... did you forget to include a link within the language name, or is it actually named "[Julia]"? – Zacharý – 2017-07-16T15:04:32.913

You are right, the name is Julia without brackets – Tanj – 2017-07-16T15:08:31.730

You might want to fix that on your other answers as well! – Zacharý – 2017-07-16T15:09:19.580

Wow, that was a lot of answers! And if you want to insert a link, the syntax is [Text to display](link to website) – Zacharý – 2017-07-16T15:23:37.187