# Blog

## Archive

Show me a Random Blog Post**2017**

**2016**

**2015**

**2014**

**2013**

**2012**

## Tags

folding paper folding tube maps london underground platonic solids rhombicuboctahedron raspberry pi weather station programming python php news royal baby probability game show probability christmas flexagons frobel coins reuleaux polygons countdown football world cup sport stickers tennis braiding craft wool emf camp people maths trigonometry logic propositional calculus twitter mathslogicbot oeis pac-man graph theory video games games chalkdust magazine menace machine learning javascript martin gardner reddit national lottery rugby puzzles advent game of life dragon curves fractals pythagoras geometry triangles european cup dates palindromes chalkdust christmas card bubble bobble asteroids final fantasy curvature binary arithmetic bodmas**2016-10-08 12:39:14**

## Logical Contradictions

During my EMF talk this year, I spoke about @mathslogicbot, my Twitter bot that is working its way through the tautologies in propositional calculus. My talk included my conjecture that the number of tautologies of length \(n\) is an increasing sequence (except when \(n=8\)). After my talk, Henry Segerman suggested that I also look at the number of contradictions of length \(n\) to look for insights.

A contradiction is the opposite of a tautology: it is a formula that is False for every assignment of truth values to the variables. For example, here are a few contradictions:

$$\neg(a\leftrightarrow a)$$
$$\neg(a\rightarrow a)$$
$$(\neg a\wedge a)$$
$$(\neg a\leftrightarrow a)$$
The first eleven terms of the sequence whose \(n\)

$$0, 0, 0, 0, 0, 6, 2, 20, 6, 127, 154$$
^{th}term is the number of contradictions of length \(n\) are:This sequence is A277275 on OEIS. A list of contractions can be found here.

For the same reasons as the sequence of tautologies, I would expect this sequence to be increasing. Surprisingly, it is not increasing for small values of \(n\), but I again conjecture that it is increasing after a certain point.

### Properties of the Sequences

There are some properties of the two sequences that we can show. Let \(a(n)\) be the number of tautolgies of length \(n\) and let \(b(n)\) be the number of contradictions of length \(n\).

First, the number of tautologies and contradictions, \(a(n)+b(n)\), (A277276) is an increasing sequence. This is due to the facts that \(a(n+1)\geq b(n)\) and \(b(n+1)\geq a(n)\), as every tautology of length \(n\) becomes a contraction of length \(n+1\) by appending a \(\neg\) to be start and vice versa.

This implies that for each \(n\), at most one of \(a\) and \(b\) can be decreasing at \(n\), as if both were decreasing, then \(a+b\) would be decreasing. Sadly, this doesn't seem to give us a way to prove the conjectures, but it is a small amount of progress towards them.

### Similar Posts

Logic Bot, pt. 2 | Logic Bot | How OEISbot Works | Raspberry Pi Weather Station |

### Comments

Comments in green were written by me. Comments in blue were not written by me.

**2016-10-06 16:07:36**

## Palindromic Dates

Thanks to Marc, I noticed that today's date is a palindrome in two different date formats—DMMYY (61016) and DMMYYYY (6102016).

This made me wonder when there will be another date that is palindromic in multiple date formats, so I wrote a Python script to find out.

Turns out there's not too long to wait: 10 July 2017 will be palindromic in two date formats (MDDYY and MDDYYYY). But before that, there's 1 July 2017, which is palindromic in three date formats (YYMMD, YYMD and MDYY). Most exciting of all, however, is 2 February 2020, which is palindromic in 7 different formats!

The next palindromic dates are shown in the following table. It will update as the dates pass.

\(n\) | Next day with \(\geq n\) palindromic formats | Formats |

1 | 1 July 2017 | YYMMD,YYMD,MDYY |

2 | 1 July 2017 | YYMMD,YYMD,MDYY |

3 | 1 July 2017 | YYMMD,YYMD,MDYY |

4 | 2 February 2020 | YYYYMMDD,DDMMYYYY,MMDDYYYY,YYYYMDD,YYMDD,DDMYY,MMDYY |

5 | 2 February 2020 | YYYYMMDD,DDMMYYYY,MMDDYYYY,YYYYMDD,YYMDD,DDMYY,MMDYY |

6 | 2 February 2020 | YYYYMMDD,DDMMYYYY,MMDDYYYY,YYYYMDD,YYMDD,DDMYY,MMDYY |

7 | 2 February 2020 | YYYYMMDD,DDMMYYYY,MMDDYYYY,YYYYMDD,YYMDD,DDMYY,MMDYY |

A full list of future palindromic dates can be found here.

### Similar Posts

Logical Contradictions | Dragon Curves | How OEISbot Works | Logic Bot, pt. 2 |

### Comments

Comments in green were written by me. Comments in blue were not written by me.

**Add a Comment**

**2016-03-30 10:19:50**

## Dragon Curves

Take a piece of paper. Fold it in half in the same direction many times. Now unfold it. What pattern will the folds make?

I first found this question in one of Martin Gardner's books. At first, you might that the answer will be simple, but if you look at the shapes made for a few folds, you will see otherwise:

The curves formed are called

*dragon curves*as they allegedly look like dragons with smoke rising from their nostrils. I'm not sure I see the resemblance:As you increase the order of the curve (the number of times the paper was folded), the dragon curve squiggles across more of the plane, while never crossing itself. In fact, if the process was continued forever, an order infinity dragon curve would cover the whole plane, never crossing itself.

This is not the only way to cover a plane with dragon curves: the curves tessellate.

Dragon curves of different orders can also fit together:

### Drawing Dragon Curves

To generate digital dragon curves, first notice that an order \(n\) curve can be made from two order \(n-1\) curves:

This can easily be seen to be true if you consider folding paper: If you fold a strip of paper in half once, then \(n-1\) times, each half of the strip will have made an order \(n-1\) dragon curve. But the whole strip has been folded \(n\) times, so is an order \(n\) dragon curve.

Because of this, higher order dragons can be thought of as lots of lower order dragons tiled together. An the infinite dragon curve is actually equivalent to tiling the plane with a infinite number of dragons.

If you would like to create your own dragon curves, you can download the Python code I used to draw them from GitHub. If you are more of a thinker, then you might like to ponder what difference it would make if the folds used to make the dragon were in different directions.

### Similar Posts

Logical Contradictions | Palindromic Dates | Tube Map Kaleidocycles | Making Names in Life |

### Comments

Comments in green were written by me. Comments in blue were not written by me.

**Add a Comment**

**2015-08-29 08:48:00**

## How OEISbot Works

A few weeks ago, I made OEISbot, a Reddit bot which posts information whenever an OEIS sequence is mentioned.

This post explaind how OEISbot works. The full code can be found on GitHub.

### Getting Started

OEISbot is made in Python using PRAW (Python Reddit Api Wrapper). PRAW can be installed with:

pip install praw

Before making a bot, you will need to make a Reddit account for your bot, create a Reddit app and obtain API keys. This python script can be used to obtain the necessary keys.

Once you have your API keys saved in your praw.ini file, you are ready to make a bot.

### Writing the Bot

First, the necessary imports are made.

import praw

import re

import urllib

import json

from praw.objects import MoreComments

import re

import urllib

import json

from praw.objects import MoreComments

To prevent OEISbot from posting multiple links to the same sequence in a thread, a list of all the sequences which have been linked to is loaded.

with open("/home/pi/OEIS/seen") as f:

seen = json.load(f)

seen = json.load(f)

Next, OEISbot logs into Reddit.

r = praw.Reddit('OEIS link and description poster by /u/mscroggs.')

access_i = r.refresh_access_information(refresh_token=r.refresh_token)

r.set_access_credentials(**access_i)

auth = r.get_me()

access_i = r.refresh_access_information(refresh_token=r.refresh_token)

r.set_access_credentials(**access_i)

auth = r.get_me()

The subs which OEISbot will search through are listed. I have used all the math(s) subs which I know about, as these will be the ones mentioning sequences.

subs = ['math','mathpuzzles','casualmath','theydidthemath',

'learnmath','mathbooks','cheatatmathhomework','matheducation',

'puremathematics','mathpics','mathriddles','askmath']

'learnmath','mathbooks','cheatatmathhomework','matheducation',

'puremathematics','mathpics','mathriddles','askmath']

The markup function loads the necessary information from OEIS and formats it. Each comment will end with the output of the me function. The ouput of joiner will be used between sequences which are mentioned.

def markup(seq_n):

pattern = re.compile("%N (.*?)<",re.DOTALL|re.M)

desc=urllib.urlopen("http://oeis.org/A"+seq_n+"/internal").read()

desc=pattern.findall(desc)[0].strip("\n")

pattern = re.compile("%S (.*?)<",re.DOTALL|re.M)

seq=urllib.urlopen("http://oeis.org/A"+seq_n+"/internal").read()

seq=pattern.findall(seq)[0].strip("\n")

new_com = "[A"+seq_n+"](http://oeis.org/A"+seq_n+"/): "

new_com += desc+"\n\n"

new_com += seq+"..."

return new_com

def me():

return "I am OEISbot. I was programmed by /u/mscroggs. [How I work](http://mscroggs.co.uk/blog/20)."

def joiner():

return "\n\n- - - -\n\n"

pattern = re.compile("%N (.*?)<",re.DOTALL|re.M)

desc=urllib.urlopen("http://oeis.org/A"+seq_n+"/internal").read()

desc=pattern.findall(desc)[0].strip("\n")

pattern = re.compile("%S (.*?)<",re.DOTALL|re.M)

seq=urllib.urlopen("http://oeis.org/A"+seq_n+"/internal").read()

seq=pattern.findall(seq)[0].strip("\n")

new_com = "[A"+seq_n+"](http://oeis.org/A"+seq_n+"/): "

new_com += desc+"\n\n"

new_com += seq+"..."

return new_com

def me():

return "I am OEISbot. I was programmed by /u/mscroggs. [How I work](http://mscroggs.co.uk/blog/20)."

def joiner():

return "\n\n- - - -\n\n"

For each sub OEISbot is monitoring, the hottest 10 posts are searched through for mentions of sequences. If a mention is found, a reply is generated and posted.

for sub in subs:

subreddit = r.get_subreddit(sub)

for submission in subreddit.get_hot(limit = 10):

try:

seen[submission.id]

except KeyError:

seen[submission.id] = []

re_s = re.findall("A([0-9]{6})",submission.title)

re_s += re.findall("oeis\.org/A([0-9]{6})",submission.url)

post_me = []

for seq_n in re_s:

if seq_n not in seen[submission.id]:

post_me.append(markup(seq_n))

seen[submission.id].append(seq_n)

if len(post_me)>0:

post_me.append(me())

submission.add_comment(joiner().join(post_me))

break

flat_comments = praw.helpers.flatten_tree(submission.comments)

for comment in flat_comments:

if not isinstance(comment,MoreComments) and comment.author is not None and comment.author.name != "OEISbot":

re_s = re.findall("A([0-9]{6})",comment.body)

post_me = []

for seq_n in re_s:

if seq_n not in seen[submission.id]:

post_me.append(markup(seq_n))

seen[submission.id].append(seq_n)

if len(post_me)>0:

post_me.append(me())

comment.reply(joiner().join(post_me))

break

else:

continue

break

else:

continue

break

subreddit = r.get_subreddit(sub)

for submission in subreddit.get_hot(limit = 10):

try:

seen[submission.id]

except KeyError:

seen[submission.id] = []

re_s = re.findall("A([0-9]{6})",submission.title)

re_s += re.findall("oeis\.org/A([0-9]{6})",submission.url)

post_me = []

for seq_n in re_s:

if seq_n not in seen[submission.id]:

post_me.append(markup(seq_n))

seen[submission.id].append(seq_n)

if len(post_me)>0:

post_me.append(me())

submission.add_comment(joiner().join(post_me))

break

flat_comments = praw.helpers.flatten_tree(submission.comments)

for comment in flat_comments:

if not isinstance(comment,MoreComments) and comment.author is not None and comment.author.name != "OEISbot":

re_s = re.findall("A([0-9]{6})",comment.body)

post_me = []

for seq_n in re_s:

if seq_n not in seen[submission.id]:

post_me.append(markup(seq_n))

seen[submission.id].append(seq_n)

if len(post_me)>0:

post_me.append(me())

comment.reply(joiner().join(post_me))

break

else:

continue

break

else:

continue

break

The list of sequences which have been posted in each thread is saved to prevent duplication later.

with open("/home/pi/OEIS/seen","w") as f:

json.dump(seen,f)

json.dump(seen,f)

### Running the Code

I put this script on a Raspberry Pi which runs it every 10 minutes (to prevent OEISbot from getting refusals for posting too often). This is achieved with a cron job.

*/10 * * * * python /path/to/bot.py

### Making Your Own Bot

The full OEISbot code is available on GitHub. Feel free to use it as a starting point to make your own bot! If your bot is successful, let me know about it in the comments below or on Twitter.

### Similar Posts

Logical Contradictions | Logic Bot, pt. 2 | Logic Bot | Raspberry Pi Weather Station |

### Comments

Comments in green were written by me. Comments in blue were not written by me.

**Add a Comment**

**2015-03-15 15:14:29**

## Logic Bot, pt. 2

A few months ago, I set
@mathslogicbot going on the
long task of tweeting all the tautologies (containing 140 characters or less)
in propositional calculus with the symbols \(\neg\) (not), \(\rightarrow\)
(implies), \(\leftrightarrow\) (if and only if), \(\wedge\) (and) and \(\vee\)
(or). My first post on logic bot contains a full
explanation of propositional calculus, formulae and tautologies.

### An Alternative Method

Since writing the original post, I have written an alternative script to
generate all the tautologies.
In this new method, I run through all possible strings of length 1 made
with character in the logical language, then strings of length 2, 3 and so on.
The script then checks if they are valid formulae and, if so, if they are
tautologies.

In the new script, only formulae where the first appearances of variables
are in alphabetical order are considered. This means that duplicate tautologies
are removed. For example, \((b\rightarrow(b\wedge a))\) will not be counted as
it is the same as \((a\rightarrow(a\wedge b))\).

You can view or download this alternative code on
github.
All the terms of the sequence that I have calculated so far can be viewed
here and the tautologies for these terms are
here.

### Sequence

One advantage of this method is that it generates the tautologies sorted by
the number of symbols they contain, meaning we can generate the sequence whose
\(n\)

^{th}term is the number of tautologies of length \(n\).The first ten terms of this sequence are

$$0, 0, 0, 0, 2, 2, 12, 6, 57, 88$$
as there are no tautologies of length less than 5; and, for example two
tautologies of length 6 (\((\neg a\vee a)\) and \((a\vee \neg a)\)).

This sequence is listed as
A256120 on OEIS.

#### Properties

There are a few properties of this sequence that can easily be shown.
Throughout this section I will use \(a_n\) to represent the \(n\)

^{th}term of the sequence.Firstly, \(a_{n+2}\geq a_n\). This can be explained as follows: let \(A\)
be a tautology of length \(n\). \(\neg\neg A\) will be of length \(n+2\) and
is logically equivalent to \(A\).

Another property is \(a_{n+4}\geq 2a_n\): given a tautology \(A\) of length
\(n\), both \((a\vee A)\) and \((A\vee a)\) will be tautologies of length
\(n+4\). Similar properties could be shown for \(\rightarrow\),
\(\leftrightarrow\) and \(\wedge\).

Given properties like this, one might predict that the sequence will be
increasing (\(a_{n+1}\geq a_n\)). However this is not true as \(a_7\) is 12
and \(a_8\) is only 6. It would be interesting to know at how many points in
the sequence there is a term that is less than the previous one. Given the
properties above it is reasonable to conjecture that this is the only one.

Edit: The sequence has been published on OEIS!

### Similar Posts

Logical Contradictions | Logic Bot | How OEISbot Works | Raspberry Pi Weather Station |

### Comments

Comments in green were written by me. Comments in blue were not written by me.

**Add a Comment**

Add a Comment