Skip to main content
added 2484 characters in body
Source Link

I wrote the following Haskell program which generates polyplets of size n and checks them forfinds vanishing cases. Currently it ignores the symmetries of possible solutionspolyplets.

data Polyplet = Polyplet {
 members :: [(Int,Int)]
}
,
instance Eqnonmembers Polyplet:: where[(Int,Int)]
} (Polypletderiving a)Show

eq ==:: (PolypletEq ba) ==> filter(`notElem`a)b[a] ++-> filter(`notElem`b)a[a] ==-> []Bool
eq [] [] = True
(Polypleteq a) ![] (Polyplet = False
eq [] b)  = filterFalse
eq (`notElem`at:a) b ++= eq a (filter (`notElem`b/=t)a == []b)

instance ShowEq Polyplet where
 show (Polyplet pa _) === unlines(Polyplet [[ifb elem_) = any (x,yeq a) p[zero then$ f $ '*'g else$ 'b|f<-[id,syma,syma.syma,syma.syma.syma],g<-[id,symb]]

syma '|x<p = [(b,-rangify[x|a)|(xa,_b)<-p]]|y<p] 
symb p = [(-rangify[y|a,b)|(_a,yb)<-p]]p]

childrensize :: Polyplet -> [Polyplet]Int
childrensize polyplet@(Polyplet p _) = [zero $ Polyplet $length cp

zero :: [(Int,Int)] -> [(Int,Int)]
zero p |= cdo
 let mx = minimum [x|(x,_)<-p];
 uniquifylet $my allDeads= polyplet]minimum [y|(_,y)<-p];
 [(x-mx,y-my)|(x,y)<-p];

zerozeroPolyplet :: Polyplet -> Polyplet
zerozeroPolyplet (Polyplet p np) = do
 let mx = minimum [x|(x,_)<-p];
 let my = minimum [y|(_,y)<-p];
 Polyplet[Polyplet [(x-mx,y-my)|(x,y)<-p];p] [(x-mx,y-my)|(x,y)<-np]

rangify l = [minimum l..maximum l]

deadsAt :: Polyplet -> (Int,Int) -> [(Int,Int)]
deadsAt (Polyplet p _) x = filter(`notElem`p) $ adjacents x  

-- Maybe rename? --
allDeads :: Polyplet -> [(Int,Int)]
allDeads polyplet@(Polyplet p np) = uniquify $$ filter (`notElem` np) $ p >>= deadsAt polyplet 

maxLive :: Polyplet -> (Int,Int) -> Int
maxLive (Polyplet _ np) x = sum [1|u<-adjacents x,notElem u np]

minLive :: Polyplet -> (Int,Int) -> Int
minLive (Polyplet p _) x = 8 - sum [1|u<-adjacents x,notElem u p]

-- Could this be made faster? --
uniquify :: (Eq a) => [a] -> [a]
uniquify u = [a|(a,b) <- zip u [0..],notElem a $ take b u]

adjacents :: (Int,Int) -> [(Int,Int)]
adjacents (a,b) = [(a+x,b+y)|x<-[-1..1],y<-[-1..1],(x,y)/=(0,0)]

sizeNpolyplets :: Int -> [Polyplet]
sizeNpolyplets 1 = [Polyplet [(0,0)]]
sizeNpolyplets n = uniquify $ sizeNpolyplets (n-1) >>= children

vanishingforbiddenMinor :: Polyplet -> Bool
vanishingforbiddenMinor polyplet@(Polyplet p) = all ((`notElem`[5,6]np).length.deadsAt polyplet)= [1|lCell<-p && all ((/=5).length.deadsAt,maxLive polyplet) (allDeadslCell<4,minLive polyplet)

Try it online!

You can envoke it like so in ghci

mapM_ print $ filter vanishing $ sizeNpolypletslCell>1] 7

This will make a nice little ascii diagram of the found polyplets. If you want the raw data you can use

mapM_++ (print.members)[1|dCell<-np,maxLive $ filter vanishing $polyplet sizeNpolypletsdCell 7

instead.

The program is not very fast but I have been able to confirm that there are no solutions of size $2\leq n\leq 8$ using my laptop. Perhaps better techniques/more powerful computers can exhaust larger cases.


Here is an alternative version of the program that takes into account symmetry when calculating values. It may be slower than the above implementation especially for smaller inputs.

data== Polyplet3,minLive =polyplet PolypletdCell {
== members3] ::== [(Int,Int)]
}[]

eqpartitions :: (Num a,Eq a) => [a]a -> [a][b] -> Bool[([b],[b])]
eqpartitions []_ [] = True
eq a [([]  = False
eq ,[] b  = False
eq (t:a) b]
partitions =0 eqx a (filter= [(/=t) b[],x)

instance Eq Polyplet where]
 (Polyplet a)partitions ==n (Polyplet bx:xs) = any (eq a) [zero $ f $ g $ b|f<-[id,syma,syma.syma,syma.syma.syma],g<-[id,symb]]

syma p =map [(b,-a)|\(a,b)<-p] 
symb p = [(-a,b)|> (x:a,b)<-p]
 
instance Show Polyplet where
 show (Polyplet p) = unlines [[if elem (x,y) p then '*'$ partitions (n-1) xs) ++ (map (\(a,b) -> (a,x:b)) $ elsepartitions 'n '|x<-rangify[x|(x,_)<-p]]|y<-rangify[y|(_,yxs)<-p]]

childrensubPolyplets :: Int -> Polyplet -> [Polyplet]
childrensubPolyplets max polyplet@(Polyplet p np) = [Polyplet $ zero $ c(addingLive :++ p) |(addingDead c++ np)|(addingLive,addingDead) <- uniquifyinit $$ partitions max $ allDeads polyplet] 

zerozipCat :: [(Int,Int)][[a]] -> [(Int,Int)]
zero p[[a]] =-> do[[a]]
zipCat let[] mxb = minimum [x|(x,_)<-p];b
zipCat leta my[] = minimuma
zipCat [y|(_,ya:as)<-p];
 [(x-mx,y-myb:bs)| = (x,y)<-p];

rangifya l++ =b): [minimumzipCat l..maximumas l]bs

deadsAtregroup :: Polyplet[Polyplet] -> (Int,Int)[[Polyplet]]
regroup ->[] [(Int,Int)]= []
deadsAtregroup (Polyplet p) x:xs) = filterzipCat (`notElem`pregroup xs) $ adjacents x 

allDeads :: Polyplet ->replicate [(Int,Int)]
allDeadslength polyplet@(Polypletmembers px) = uniquify $- p1) >>=[] deadsAt++ polyplet[[x]]

uniquifyfillPolyplets :: (Eq a)Int =>-> [a]Int -> [a][[Polyplet]]
uniquifyfillPolyplets u1 n = [a|[Polyplet [(a0,b0) <- zip u [0..],notElem a[]] $: takereplicate b(n-1) u]
[]
adjacentsfillPolyplets ::x (Int,Int)n ->= [(Int,Int)]do
adjacents (a,b)let previous = [fillPolyplets (a+x,b+y)|x<-[-1..1],y<-[x-1..1],(x,y)/=(0,0)]
 n
sizeNpolyplets ::zipCat Intprevious ->$ map (filter forbiddenMinor . uniquify . map zeroPolyplet) $ [Polyplet]
sizeNpolypletsregroup 1$ =(previous [Polyplet!! [(0,0x-2)]]
sizeNpolyplets n = uniquify) $>>= sizeNpolypletssubPolyplets (n-1x+1) >>= children

noChildrenvanishing :: Polyplet -> Bool
noChildrenvanishing polyplet@(Polyplet p np) = all ((/=5`notElem`[5,6]).length.deadsAt polyplet) (allDeads polyplet)

noSurvivors :: Polyplet -> Bool
noSurvivors polyplet@(Polyplet p) =&& all ((`notElem`[5,6]/=5).length.deadsAt polyplet) p(allDeads polyplet ++ np)

vanishinggetVanishingPolyplets :: PolypletInt -> Bool[Polyplet]
vanishinggetVanishingPolyplets pn = noChildrenfillPolyplets pn &&n noSurvivors>>= p(filter vanishing)

Try it online!

You can envoke it like so in ghci

mapM_ (print.members) $ getVanishingPolyplets 7

The program is not very fast but I have been able to get a complete classification for vanishing polyplets of size $n \leq 12$. Perhaps better techniques/more powerful computers can exhaust larger cases.

Here are the results of running it on $n=12$:

$$ \substack{ \displaystyle{◻◻◻} \cr \displaystyle{◻◼◻} \cr \displaystyle{◻◻◻} \cr } \quad \quad \quad \substack{ \displaystyle{◻◻◻◻} \cr \displaystyle{◻◼◼◻} \cr \displaystyle{◻◻◻◻} \cr } \quad \quad \quad \substack{ \displaystyle{◻◻◻◻} \cr \displaystyle{◻◻◼◻} \cr \displaystyle{◻◼◻◻} \cr \displaystyle{◻◻◻◻} \cr } \quad \quad \quad \substack{ \displaystyle{◻◻◻◻◻◻◻} \cr \displaystyle{◻◻◻◼◻◻◻} \cr \displaystyle{◻◻◻◼◻◻◻} \cr \displaystyle{◻◼◼◼◼◼◻} \cr \displaystyle{◻◻◻◼◻◻◻} \cr \displaystyle{◻◻◻◼◻◻◻} \cr \displaystyle{◻◻◻◻◻◻◻} \cr } \quad \quad \quad \substack{ \displaystyle{◻◻◻◻◻◻◻} \cr \displaystyle{◻◻◻◻◼◻◻} \cr \displaystyle{◻◼◻◼◻◻◻} \cr \displaystyle{◻◻◼◼◼◻◻} \cr \displaystyle{◻◻◻◼◻◼◻} \cr \displaystyle{◻◻◼◻◻◻◻} \cr \displaystyle{◻◻◻◻◻◻◻} \cr } $$ $$ \substack{ \displaystyle{◻◻◻◻◻◻◻◻} \cr \displaystyle{◻◻◻◼◼◻◻◻} \cr \displaystyle{◻◼◼◼◼◼◼◻} \cr \displaystyle{◻◻◻◼◼◻◻◻} \cr \displaystyle{◻◻◻◻◻◻◻◻} \cr } \quad \quad \quad \substack{ \displaystyle{◻◻◻◻◻◻◻◻} \cr \displaystyle{◻◻◻◼◻◻◻◻} \cr \displaystyle{◻◻◻◻◼◻◻◻} \cr \displaystyle{◻◻◻◼◼◼◼◻} \cr \displaystyle{◻◼◼◼◼◻◻◻} \cr \displaystyle{◻◻◻◼◻◻◻◻} \cr \displaystyle{◻◻◻◻◼◻◻◻} \cr \displaystyle{◻◻◻◻◻◻◻◻} \cr } \quad \quad \quad \substack{ \displaystyle{◻◻◻◻◻◻◻◻} \cr \displaystyle{◻◻◻◼◻◻◻◻} \cr \displaystyle{◻◻◻◻◼◻◻◻} \cr \displaystyle{◻◻◻◼◼◼◼◻} \cr \displaystyle{◻◼◼◼◼◻◻◻} \cr \displaystyle{◻◻◻◼◻◻◻◻} \cr \displaystyle{◻◻◻◼◻◻◻◻} \cr \displaystyle{◻◻◻◻◻◻◻◻} \cr } \quad \quad \quad \substack{ \displaystyle{◻◻◻◻◻◻◻◻} \cr \displaystyle{◻◻◻◻◼◻◻◻} \cr \displaystyle{◻◻◻◻◼◻◻◻} \cr \displaystyle{◻◻◻◼◼◼◼◻} \cr \displaystyle{◻◼◼◼◼◻◻◻} \cr \displaystyle{◻◻◻◼◻◻◻◻} \cr \displaystyle{◻◻◻◼◻◻◻◻} \cr \displaystyle{◻◻◻◻◻◻◻◻} \cr } $$

All of these were previously found by others, however now we can be certain that there are no other vanishing polyplets of size less than $12$ that we are unaware of.

There also seems to be an issue that some polyplets show up in the output more times than they should. I think this is a problem with the way I handle symmetries but I can't nail it down for sure. Fixing this problem would probably make things considerably faster.

I wrote the following Haskell program which generates polyplets of size n and checks them for vanishing cases. Currently it ignores the symmetries of possible solutions.

data Polyplet = Polyplet {
 members :: [(Int,Int)]
}

instance Eq Polyplet where
 (Polyplet a) == (Polyplet b) = filter(`notElem`a)b ++ filter(`notElem`b)a == []
 
(Polyplet a) ! (Polyplet b) = filter(`notElem`a)b ++ filter(`notElem`b)a == []

instance Show Polyplet where
 show (Polyplet p) = unlines [[if elem (x,y) p then '*' else ' '|x<-rangify[x|(x,_)<-p]]|y<-rangify[y|(_,y)<-p]]

children :: Polyplet -> [Polyplet]
children polyplet@(Polyplet p) = [zero $ Polyplet $ c : p | c <- uniquify $ allDeads polyplet] 

zero :: Polyplet -> Polyplet
zero (Polyplet p) = do
 let mx = minimum [x|(x,_)<-p];
 let my = minimum [y|(_,y)<-p];
 Polyplet[(x-mx,y-my)|(x,y)<-p];

rangify l = [minimum l..maximum l]

deadsAt :: Polyplet -> (Int,Int) -> [(Int,Int)]
deadsAt (Polyplet p) x = filter(`notElem`p) $ adjacents x 

allDeads :: Polyplet -> [(Int,Int)]
allDeads polyplet@(Polyplet p) = uniquify $ p >>= deadsAt polyplet

uniquify :: (Eq a) => [a] -> [a]
uniquify u = [a|(a,b) <- zip u [0..],notElem a $ take b u]

adjacents :: (Int,Int) -> [(Int,Int)]
adjacents (a,b) = [(a+x,b+y)|x<-[-1..1],y<-[-1..1],(x,y)/=(0,0)]

sizeNpolyplets :: Int -> [Polyplet]
sizeNpolyplets 1 = [Polyplet [(0,0)]]
sizeNpolyplets n = uniquify $ sizeNpolyplets (n-1) >>= children

vanishing :: Polyplet -> Bool
vanishing polyplet@(Polyplet p) = all ((`notElem`[5,6]).length.deadsAt polyplet) p && all ((/=5).length.deadsAt polyplet) (allDeads polyplet)

Try it online!

You can envoke it like so in ghci

mapM_ print $ filter vanishing $ sizeNpolyplets 7

This will make a nice little ascii diagram of the found polyplets. If you want the raw data you can use

mapM_ (print.members) $ filter vanishing $ sizeNpolyplets 7

instead.

The program is not very fast but I have been able to confirm that there are no solutions of size $2\leq n\leq 8$ using my laptop. Perhaps better techniques/more powerful computers can exhaust larger cases.


Here is an alternative version of the program that takes into account symmetry when calculating values. It may be slower than the above implementation especially for smaller inputs.

data Polyplet = Polyplet {
 members :: [(Int,Int)]
}

eq :: (Eq a) => [a] -> [a] -> Bool
eq [] [] = True
eq a []  = False
eq [] b  = False
eq (t:a) b = eq a (filter (/=t) b)

instance Eq Polyplet where
 (Polyplet a) == (Polyplet b) = any (eq a) [zero $ f $ g $ b|f<-[id,syma,syma.syma,syma.syma.syma],g<-[id,symb]]

syma p = [(b,-a)|(a,b)<-p] 
symb p = [(-a,b)|(a,b)<-p]
 
instance Show Polyplet where
 show (Polyplet p) = unlines [[if elem (x,y) p then '*' else ' '|x<-rangify[x|(x,_)<-p]]|y<-rangify[y|(_,y)<-p]]

children :: Polyplet -> [Polyplet]
children polyplet@(Polyplet p) = [Polyplet $ zero $ c : p | c <- uniquify $ allDeads polyplet] 

zero :: [(Int,Int)] -> [(Int,Int)]
zero p = do
 let mx = minimum [x|(x,_)<-p];
 let my = minimum [y|(_,y)<-p];
 [(x-mx,y-my)|(x,y)<-p];

rangify l = [minimum l..maximum l]

deadsAt :: Polyplet -> (Int,Int) -> [(Int,Int)]
deadsAt (Polyplet p) x = filter(`notElem`p) $ adjacents x 

allDeads :: Polyplet -> [(Int,Int)]
allDeads polyplet@(Polyplet p) = uniquify $ p >>= deadsAt polyplet

uniquify :: (Eq a) => [a] -> [a]
uniquify u = [a|(a,b) <- zip u [0..],notElem a $ take b u]

adjacents :: (Int,Int) -> [(Int,Int)]
adjacents (a,b) = [(a+x,b+y)|x<-[-1..1],y<-[-1..1],(x,y)/=(0,0)]

sizeNpolyplets :: Int -> [Polyplet]
sizeNpolyplets 1 = [Polyplet [(0,0)]]
sizeNpolyplets n = uniquify $ sizeNpolyplets (n-1) >>= children

noChildren :: Polyplet -> Bool
noChildren polyplet@(Polyplet p) = all ((/=5).length.deadsAt polyplet) (allDeads polyplet)

noSurvivors :: Polyplet -> Bool
noSurvivors polyplet@(Polyplet p) = all ((`notElem`[5,6]).length.deadsAt polyplet) p

vanishing :: Polyplet -> Bool
vanishing p = noChildren p && noSurvivors p

I wrote the following Haskell program which generates finds vanishing polyplets.

data Polyplet = Polyplet {
 members :: [(Int,Int)],
 nonmembers :: [(Int,Int)]
} deriving Show

eq :: (Eq a) => [a] -> [a] -> Bool
eq [] [] = True
eq a []  = False
eq [] b  = False
eq (t:a) b = eq a (filter (/=t) b)

instance Eq Polyplet where
 (Polyplet a _) == (Polyplet b _) = any (eq a) [zero $ f $ g $ b|f<-[id,syma,syma.syma,syma.syma.syma],g<-[id,symb]]

syma p = [(b,-a)|(a,b)<-p] 
symb p = [(-a,b)|(a,b)<-p]

size :: Polyplet -> Int
size (Polyplet p _) = length p

zero :: [(Int,Int)] -> [(Int,Int)]
zero p = do
 let mx = minimum [x|(x,_)<-p];
 let my = minimum [y|(_,y)<-p];
 [(x-mx,y-my)|(x,y)<-p];

zeroPolyplet :: Polyplet -> Polyplet
zeroPolyplet (Polyplet p np) = do
 let mx = minimum [x|(x,_)<-p];
 let my = minimum [y|(_,y)<-p];
 Polyplet [(x-mx,y-my)|(x,y)<-p] [(x-mx,y-my)|(x,y)<-np]

rangify l = [minimum l..maximum l]

deadsAt :: Polyplet -> (Int,Int) -> [(Int,Int)]
deadsAt (Polyplet p _) x = filter(`notElem`p) $ adjacents x  

-- Maybe rename? --
allDeads :: Polyplet -> [(Int,Int)]
allDeads polyplet@(Polyplet p np) = uniquify $ filter (`notElem` np) $ p >>= deadsAt polyplet 

maxLive :: Polyplet -> (Int,Int) -> Int
maxLive (Polyplet _ np) x = sum [1|u<-adjacents x,notElem u np]

minLive :: Polyplet -> (Int,Int) -> Int
minLive (Polyplet p _) x = 8 - sum [1|u<-adjacents x,notElem u p]

-- Could this be made faster? --
uniquify :: (Eq a) => [a] -> [a]
uniquify u = [a|(a,b) <- zip u [0..],notElem a $ take b u]

adjacents :: (Int,Int) -> [(Int,Int)]
adjacents (a,b) = [(a+x,b+y)|x<-[-1..1],y<-[-1..1],(x,y)/=(0,0)]

forbiddenMinor :: Polyplet -> Bool
forbiddenMinor polyplet@(Polyplet p np) = [1|lCell<-p,maxLive polyplet lCell<4,minLive polyplet lCell>1] ++ [1|dCell<-np,maxLive polyplet dCell == 3,minLive polyplet dCell == 3] == []

partitions :: (Num a,Eq a) => a -> [b] -> [([b],[b])]
partitions _ [] = [([],[])]
partitions 0 x  = [([],x)]
partitions n (x:xs) = (map (\(a,b) -> (x:a,b)) $ partitions (n-1) xs) ++ (map (\(a,b) -> (a,x:b)) $ partitions n xs)

subPolyplets :: Int -> Polyplet -> [Polyplet]
subPolyplets max polyplet@(Polyplet p np) = [Polyplet (addingLive ++ p) (addingDead ++ np)|(addingLive,addingDead) <- init $ partitions max $ allDeads polyplet]

zipCat :: [[a]] -> [[a]] -> [[a]]
zipCat [] b = b
zipCat a [] = a
zipCat (a:as) (b:bs) = (a ++ b): zipCat as bs

regroup :: [Polyplet] -> [[Polyplet]]
regroup [] = []
regroup (x:xs) = zipCat (regroup xs) $ replicate (length (members x) - 1) [] ++ [[x]]

fillPolyplets :: Int -> Int -> [[Polyplet]]
fillPolyplets 1 n = [Polyplet [(0,0)] []] : replicate (n-1) []
fillPolyplets x n = do
 let previous = fillPolyplets (x-1) n
 zipCat previous $ map (filter forbiddenMinor . uniquify . map zeroPolyplet) $ regroup $ (previous !! (x-2)) >>= subPolyplets (n-x+1)

vanishing :: Polyplet -> Bool
vanishing polyplet@(Polyplet p np) = all ((`notElem`[5,6]).length.deadsAt polyplet) p && all ((/=5).length.deadsAt polyplet) (allDeads polyplet ++ np)

getVanishingPolyplets :: Int -> [Polyplet]
getVanishingPolyplets n = fillPolyplets n n >>= (filter vanishing)

Try it online!

You can envoke it like so in ghci

mapM_ (print.members) $ getVanishingPolyplets 7

The program is not very fast but I have been able to get a complete classification for vanishing polyplets of size $n \leq 12$. Perhaps better techniques/more powerful computers can exhaust larger cases.

Here are the results of running it on $n=12$:

$$ \substack{ \displaystyle{◻◻◻} \cr \displaystyle{◻◼◻} \cr \displaystyle{◻◻◻} \cr } \quad \quad \quad \substack{ \displaystyle{◻◻◻◻} \cr \displaystyle{◻◼◼◻} \cr \displaystyle{◻◻◻◻} \cr } \quad \quad \quad \substack{ \displaystyle{◻◻◻◻} \cr \displaystyle{◻◻◼◻} \cr \displaystyle{◻◼◻◻} \cr \displaystyle{◻◻◻◻} \cr } \quad \quad \quad \substack{ \displaystyle{◻◻◻◻◻◻◻} \cr \displaystyle{◻◻◻◼◻◻◻} \cr \displaystyle{◻◻◻◼◻◻◻} \cr \displaystyle{◻◼◼◼◼◼◻} \cr \displaystyle{◻◻◻◼◻◻◻} \cr \displaystyle{◻◻◻◼◻◻◻} \cr \displaystyle{◻◻◻◻◻◻◻} \cr } \quad \quad \quad \substack{ \displaystyle{◻◻◻◻◻◻◻} \cr \displaystyle{◻◻◻◻◼◻◻} \cr \displaystyle{◻◼◻◼◻◻◻} \cr \displaystyle{◻◻◼◼◼◻◻} \cr \displaystyle{◻◻◻◼◻◼◻} \cr \displaystyle{◻◻◼◻◻◻◻} \cr \displaystyle{◻◻◻◻◻◻◻} \cr } $$ $$ \substack{ \displaystyle{◻◻◻◻◻◻◻◻} \cr \displaystyle{◻◻◻◼◼◻◻◻} \cr \displaystyle{◻◼◼◼◼◼◼◻} \cr \displaystyle{◻◻◻◼◼◻◻◻} \cr \displaystyle{◻◻◻◻◻◻◻◻} \cr } \quad \quad \quad \substack{ \displaystyle{◻◻◻◻◻◻◻◻} \cr \displaystyle{◻◻◻◼◻◻◻◻} \cr \displaystyle{◻◻◻◻◼◻◻◻} \cr \displaystyle{◻◻◻◼◼◼◼◻} \cr \displaystyle{◻◼◼◼◼◻◻◻} \cr \displaystyle{◻◻◻◼◻◻◻◻} \cr \displaystyle{◻◻◻◻◼◻◻◻} \cr \displaystyle{◻◻◻◻◻◻◻◻} \cr } \quad \quad \quad \substack{ \displaystyle{◻◻◻◻◻◻◻◻} \cr \displaystyle{◻◻◻◼◻◻◻◻} \cr \displaystyle{◻◻◻◻◼◻◻◻} \cr \displaystyle{◻◻◻◼◼◼◼◻} \cr \displaystyle{◻◼◼◼◼◻◻◻} \cr \displaystyle{◻◻◻◼◻◻◻◻} \cr \displaystyle{◻◻◻◼◻◻◻◻} \cr \displaystyle{◻◻◻◻◻◻◻◻} \cr } \quad \quad \quad \substack{ \displaystyle{◻◻◻◻◻◻◻◻} \cr \displaystyle{◻◻◻◻◼◻◻◻} \cr \displaystyle{◻◻◻◻◼◻◻◻} \cr \displaystyle{◻◻◻◼◼◼◼◻} \cr \displaystyle{◻◼◼◼◼◻◻◻} \cr \displaystyle{◻◻◻◼◻◻◻◻} \cr \displaystyle{◻◻◻◼◻◻◻◻} \cr \displaystyle{◻◻◻◻◻◻◻◻} \cr } $$

All of these were previously found by others, however now we can be certain that there are no other vanishing polyplets of size less than $12$ that we are unaware of.

There also seems to be an issue that some polyplets show up in the output more times than they should. I think this is a problem with the way I handle symmetries but I can't nail it down for sure. Fixing this problem would probably make things considerably faster.

Finished testing case 8
Source Link

The program is not very fast but I have been able to confirm that there are no solutions of size $2\leq n\leq 7$$2\leq n\leq 8$ using my laptop. Perhaps better techniques/more powerful computers can exhaust larger cases.

The program is not very fast but I have been able to confirm that there are no solutions of size $2\leq n\leq 7$ using my laptop. Perhaps better techniques/more powerful computers can exhaust larger cases.

The program is not very fast but I have been able to confirm that there are no solutions of size $2\leq n\leq 8$ using my laptop. Perhaps better techniques/more powerful computers can exhaust larger cases.

Added an alternative implementation
Source Link

Here is an alternative version of the program that takes into account symmetry when calculating values. It may be slower than the above implementation especially for smaller inputs.

data Polyplet = Polyplet {
 members :: [(Int,Int)]
}

eq :: (Eq a) => [a] -> [a] -> Bool
eq [] [] = True
eq a []  = False
eq [] b  = False
eq (t:a) b = eq a (filter (/=t) b)

instance Eq Polyplet where
 (Polyplet a) == (Polyplet b) = any (eq a) [zero $ f $ g $ b|f<-[id,syma,syma.syma,syma.syma.syma],g<-[id,symb]]

syma p = [(b,-a)|(a,b)<-p] 
symb p = [(-a,b)|(a,b)<-p]
 
instance Show Polyplet where
 show (Polyplet p) = unlines [[if elem (x,y) p then '*' else ' '|x<-rangify[x|(x,_)<-p]]|y<-rangify[y|(_,y)<-p]]

children :: Polyplet -> [Polyplet]
children polyplet@(Polyplet p) = [Polyplet $ zero $ c : p | c <- uniquify $ allDeads polyplet] 

zero :: [(Int,Int)] -> [(Int,Int)]
zero p = do
 let mx = minimum [x|(x,_)<-p];
 let my = minimum [y|(_,y)<-p];
 [(x-mx,y-my)|(x,y)<-p];

rangify l = [minimum l..maximum l]

deadsAt :: Polyplet -> (Int,Int) -> [(Int,Int)]
deadsAt (Polyplet p) x = filter(`notElem`p) $ adjacents x 

allDeads :: Polyplet -> [(Int,Int)]
allDeads polyplet@(Polyplet p) = uniquify $ p >>= deadsAt polyplet

uniquify :: (Eq a) => [a] -> [a]
uniquify u = [a|(a,b) <- zip u [0..],notElem a $ take b u]

adjacents :: (Int,Int) -> [(Int,Int)]
adjacents (a,b) = [(a+x,b+y)|x<-[-1..1],y<-[-1..1],(x,y)/=(0,0)]

sizeNpolyplets :: Int -> [Polyplet]
sizeNpolyplets 1 = [Polyplet [(0,0)]]
sizeNpolyplets n = uniquify $ sizeNpolyplets (n-1) >>= children

noChildren :: Polyplet -> Bool
noChildren polyplet@(Polyplet p) = all ((/=5).length.deadsAt polyplet) (allDeads polyplet)

noSurvivors :: Polyplet -> Bool
noSurvivors polyplet@(Polyplet p) = all ((`notElem`[5,6]).length.deadsAt polyplet) p

vanishing :: Polyplet -> Bool
vanishing p = noChildren p && noSurvivors p

Here is an alternative version of the program that takes into account symmetry when calculating values. It may be slower than the above implementation especially for smaller inputs.

data Polyplet = Polyplet {
 members :: [(Int,Int)]
}

eq :: (Eq a) => [a] -> [a] -> Bool
eq [] [] = True
eq a []  = False
eq [] b  = False
eq (t:a) b = eq a (filter (/=t) b)

instance Eq Polyplet where
 (Polyplet a) == (Polyplet b) = any (eq a) [zero $ f $ g $ b|f<-[id,syma,syma.syma,syma.syma.syma],g<-[id,symb]]

syma p = [(b,-a)|(a,b)<-p] 
symb p = [(-a,b)|(a,b)<-p]
 
instance Show Polyplet where
 show (Polyplet p) = unlines [[if elem (x,y) p then '*' else ' '|x<-rangify[x|(x,_)<-p]]|y<-rangify[y|(_,y)<-p]]

children :: Polyplet -> [Polyplet]
children polyplet@(Polyplet p) = [Polyplet $ zero $ c : p | c <- uniquify $ allDeads polyplet] 

zero :: [(Int,Int)] -> [(Int,Int)]
zero p = do
 let mx = minimum [x|(x,_)<-p];
 let my = minimum [y|(_,y)<-p];
 [(x-mx,y-my)|(x,y)<-p];

rangify l = [minimum l..maximum l]

deadsAt :: Polyplet -> (Int,Int) -> [(Int,Int)]
deadsAt (Polyplet p) x = filter(`notElem`p) $ adjacents x 

allDeads :: Polyplet -> [(Int,Int)]
allDeads polyplet@(Polyplet p) = uniquify $ p >>= deadsAt polyplet

uniquify :: (Eq a) => [a] -> [a]
uniquify u = [a|(a,b) <- zip u [0..],notElem a $ take b u]

adjacents :: (Int,Int) -> [(Int,Int)]
adjacents (a,b) = [(a+x,b+y)|x<-[-1..1],y<-[-1..1],(x,y)/=(0,0)]

sizeNpolyplets :: Int -> [Polyplet]
sizeNpolyplets 1 = [Polyplet [(0,0)]]
sizeNpolyplets n = uniquify $ sizeNpolyplets (n-1) >>= children

noChildren :: Polyplet -> Bool
noChildren polyplet@(Polyplet p) = all ((/=5).length.deadsAt polyplet) (allDeads polyplet)

noSurvivors :: Polyplet -> Bool
noSurvivors polyplet@(Polyplet p) = all ((`notElem`[5,6]).length.deadsAt polyplet) p

vanishing :: Polyplet -> Bool
vanishing p = noChildren p && noSurvivors p
added 1 character in body
Source Link
Loading
Source Link
Loading