Arbitrary-Length Ternary Squarefree Words

9

A string is squarefree if it contains no substring twice in a row.

It is possible to have an arbitrarily long squarefree word using a 3-letter alphabet.

Write a program which accepts a positive integer n from stdin and prints any squarefree word of length n, using characters A, B and C.

Shortest code wins.

cardboard_box

Posted 2013-01-31T22:15:03.927

Reputation: 5 150

Answers

4

GolfScript (40 27 chars)

~1,{.{!}%+}2$*1,/<{,65+}%n+

The approach is a trivial variant on one of those described in Wikipedia: the run-lengths of 1s in the Thue-Morse sequence.

If the extra trailing newline is unacceptable it can be removed at the cost of one character by replacing n with ''.

Peter Taylor

Posted 2013-01-31T22:15:03.927

Reputation: 41 901

6

Python, 94

n=input()
x=[0]
exec"x+=[1-y for y in x];"*n
print''.join('ABC'[x[i+1]-x[i]]for i in range(n))

It uses the Thue–Morse sequence method from wikipedia.

Efficient version (100 chars):

n=input()
x=[0]
while x==x[:n]:x+=[1-y for y in x]
print''.join('ABC'[x[i+1]-x[i]]for i in range(n))

grc

Posted 2013-01-31T22:15:03.927

Reputation: 18 565

1exec"x+=[1-y for y in x];"*n saves 6 chars at the expense of efficiency - but hey this is golf! – gnibbler – 2013-02-01T06:28:20.237

4

Python, 129 125 119

Using John Leech's method as described on the linked wiki page.

s='A'
n=input()
while len(s)<=n:s=''.join('ABCBCACABBCAABCCABBCACABABCBCACABBCAABC'[ord(t)%5::3]for t in s)
print s[:n]

cardboard_box

Posted 2013-01-31T22:15:03.927

Reputation: 5 150

1You could save some characters with: 'ABCBCACABBCAABCCABBCACABABCBCACABBCAABC'[ord(t)%5::3] – grc – 2013-01-31T22:34:29.360

while s[:n]==s: saves 1 more – gnibbler – 2013-02-01T02:21:37.027

3

Python2 - 112 chars

This is pretty inefficient. It generates a much much much longer string than required and then truncates it. For example the intermediate s for n=7 is 62748517 (13n) characters long

s='A'
n=input()
exec"s=''.join('ABCBCACABBCAABCCABBCACABABCBCACABBCAABC'[ord(t)%5::3]for t in s);"*n
print s[:n]

gnibbler

Posted 2013-01-31T22:15:03.927

Reputation: 14 170

2

Mathematica 159 140 134

Edit: A complete rewrite, using recursion (NestWhile). Much faster and no wasted effort.

Code

g@n_:=StringTake[NestWhile[#~StringReplace~{"A"-> "ABCBACBCABCBA","B"-> "BCACBACABCACB",
     "C"->"CABACBABCABAC"}&,"ABC",StringLength[#]<n&],n]

Usage

It takes approximately 1/40 sec to generate a ternary square free word with one million characters.

g[10]
g[53]
g[506]
AbsoluteTiming[g[10^6];]

results

Verifying

f will test whether a string is square free.

f[s_]:=StringFreeQ[s, x__~~x__]

Checking the above outputs and one case in which the string "CC" appears.

f@Out[336]
f@Out[337]
f@Out[338]
f["ABCBACBCABCBABCACBACCABCACBCABACBABCABACBCACBACABCACBA"]

True
True
True
False

DavidC

Posted 2013-01-31T22:15:03.927

Reputation: 24 524