Ulam Spirals in R and ggplot
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Having seen a twitter post speed by about Ulam Spirals I started to read up. As the story goes in 1963 Stanislaw Ulam was bored at conference and started scribbling numbers in a spiral. What he discovered was a strange diaginal pattern of Prime Numbers. I was a little bored as well, so i decided to write up some R to plot these patterns.
Here is the main function. I am sure there are more elegant ways of calculating a Ulam spiral but here is my hack. First we calculate the diagonals and then fill in the gaps.
Ulam.Spiral<-function(N){ if (even(N)){ cat(sprintf("Error: function only accepts odd integers because it a poorly written and fragile piece of code.\n")) }else{ m <- matrix(NA, nrow=(N), ncol=N) top.left<-c(1,1) bottom.right<-c(N,N) top.right<-c(1,N) bottom.left<-c(N,1) n<-N a<-N m[median(1:N),median(1:N)]<-1 while(a>=3){ # This is an adaptation of a Euler Problem 28 solution. It calculates the diaginals. m[bottom.right[1],bottom.right[2]]<- a^2 #bottom right m[top.left[1],top.left[2]]<- a^2 - 2*a + 2 # top left m[top.right[1],top.right[2]]<- a^2 - 3*a + 3 # top right m[bottom.left[1],bottom.left[2]]<- a^2 - a + 1 #bottom left #Both Horizontal Rows m[top.left[1],(top.left[2]+1):(top.right[2]-1)]<-seq( m[top.left[1],top.left[2]]-1,m[top.left[1],top.right[2]]+1) #Fill in top row m[bottom.left[1],(bottom.left[2]+1):(bottom.right[2]-1)]<-seq(m[bottom.left[1],bottom.left[2]]+1, m[bottom.left[1],bottom.right[2]]-1) #Fill in bottom row #Left Vertical Rows m[(top.left[1]+1):(bottom.left[1]-1), top.left[1]] <- seq(m[top.left[1],top.left[1]]+1, m[bottom.left[1],top.left[1]]-1)#Left Hand Row #Right Verical Row m[(top.right[1]+1):(bottom.right[2]-1),top.right[2]] <-seq(m[top.right[1],top.right[2]]-1 , m[top.right[1],top.right[2]] - (a-2) ) #drop down on square and repeat a<-a-2 top.left<-c(top.left[1]+1,top.left[2]+1) bottom.right<-c(bottom.right[1]-1,bottom.right[2]-1) top.right<-c(top.right[1]+1,top.right[2]-1) bottom.left<-c(bottom.left[1]-1,bottom.left[2]+1) } return(m) } }
Here is the output for a 5X5 spiral
[,1] [,2] [,3] [,4] [,5] [1,] 17 16 15 14 13 [2,] 18 5 4 3 12 [3,] 19 6 1 2 11 [4,] 20 7 8 9 10 [5,] 21 22 23 24 25
The code is on git hub. https://github.com/jofusa/ulam-spirals-R
Many Thanks to http://librestats.wordpress.com/2011/08/20/prime-testing-function-in-r/ for a useful IsPrime() function and saving me some time.
Here is an example Plot- Prime Number are in red:
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.