[R] A little exercise in R!

Philippe Grosjean phgrosjean at sciviews.org
Sat Apr 14 03:26:18 CEST 2012


Hi all,

I got another solution, and it would apply probably for the ugliest one :-(
I made it general enough so that it works for any series from 1 to n (n 
not too large, please... tested up to 30).

Hint for a better algorithm: inspect the object 'friends' in my code: 
there is a nice pattern appearing there!!!

Best,

Philippe

..............................................<¡}))><........
  ) ) ) ) )
( ( ( ( (    Prof. Philippe Grosjean
  ) ) ) ) )
( ( ( ( (    Numerical Ecology of Aquatic Systems
  ) ) ) ) )   Mons University, Belgium
( ( ( ( (
..............................................................

findSerie <- function (n, tmax = 500) {
   ## Check arguments
   n <- as.integer(n)
   if (length(n) != 1 || is.na(n) || n < 1)
     stop("'n' must be a single positive integer")
	
   tmax <- as.integer(tmax)
   if (length(tmax) != 1 || is.na(tmax) || tmax < 1)
     stop("'tmax' must be a single positive integer")
	
   ## Suite of our numbers to be sorted
   nbrs <- 1:n
	
   ## Trivial cases: only one or two numbers
   if (n == 1) return(1)
   if (n == 2) stop("The pair does not sum to a square number")
	
   ## Compute all possible pairs
   omat <- outer(rep(1, n), nbrs)	
   ## Which pairs sum to a square number?
   friends <- sqrt(omat + nbrs) %% 1 < .Machine$double.eps
   diag(friends) <- FALSE # Eliminate pairs of same numbers
	
   ## Get a list of possible neighbours
   neigb <- apply(friends, 1, function(x) nbrs[x])
	
   ## Nbr of neighbours for each number
   nf <- sapply(neigb, length)
	
   ## Are there numbers without neighbours?
   ## then, problem impossible to solve..
   if (any(!nf))
     stop("Impossible to solve:\n    ",
       paste(nbrs[!nf], collapse = ", "),
       " sum to square with nobody else!")
	
   ## Are there numbers that can have only one neighbour?
   ## Must be placed at one extreme
   toEnds <- nbrs[nf == 1]
   ## I must have two of them maximum!
   l <- length(toEnds)
   if (l > 2)
     stop("Impossible to solve:\n    ",
       "More than two numbers form only one pair:\n    ",
       paste(toEnds, collapse = ", "))
	
   ## The other numbers can appear in the middle of the suite
   inMiddle <- nbrs[!nbrs %in% toEnds]
	
   generateSerie <- function (neigb, toEnds, inMiddle) {
     ## Allow to generate serie by picking candidates randomly
     if (length(toEnds) > 1) toEnds <- sample(toEnds)
     if (length(inMiddle) > 1) inMiddle <- sample(inMiddle)
		
     ## Choose a number to start with
     res <- rep(NA, n)
		
     ## Three cases: 0, 1, or 2 numbers that must be at an extreme
     ## Following code works in all cases
     res[1] <- toEnds[1]
     res[n] <- toEnds[2]
		
     ## List of already taken numbers
     taken <- toEnds
		
     ## Is there one number in res[1]? Otherwise, fill it now...
     if (is.na(res[1])) {
         taken <- inMiddle[1]
         res[1] <- taken
     }
		
     ## For each number in the middle, choose one acceptable neighbour
     for (ii in 2:(n-1)) {
       prev <- res[ii - 1]
       allpossible <- neigb[[prev]]
       candidate <- allpossible[!(allpossible %in% taken)]
       if (!length(candidate)) break # We fail to construct the serie
       ## Take randomly one possible candidate
       if (length(candidate) > 1) take <- sample(candidate, 1) else
         take <- candidate
       res[ii] <- take
       taken <- c(taken, take)
     }
		
     ## If we manage to go to the end, check last pair...
     if (length(taken) == (n - 1)) {
       take <- nbrs[!(nbrs %in% taken)]
       res[n] <- take
       taken <- c(take, taken)
     }
     if (length(taken) == n && !(res[n] %in% neigb[[res[n - 1]]]))
     res[n] <- NA # Last one pair not allowed

     ## Return the series
     return(res)
   }
	
   for (trial in 1:tmax) {
     cat("Trial", trial, ":")
     serie <- generateSerie(neigb = neigb, toEnds = toEnds,
       inMiddle = inMiddle)
     cat(paste(serie, collapse = ", "), "\n")
     flush.console() # Print text now
     if (!any(is.na(serie))) break
   }
   if (any(is.na(serie))) {
     cat("\nSorry, I did not find a solution\n\n")
   } else cat("\n** I got it! **\n\n")
   return(serie)
}

findSerie(17)


On 13/04/12 23:34, (Ted Harding) wrote:
> Greetings all!
> A recent news item got me thinking that a problem stated
> therein could provide a teasing little exercise in R
> programming.
>
> http://www.bbc.co.uk/news/uk-england-cambridgeshire-17680326
>
>    Cambridge University hosts first European 'maths Olympiad'
>    for girls
>
>    The first European girls-only "mathematical Olympiad"
>    competition is being hosted by Cambridge University.
>    [...]
>    Olympiad co-director, Dr Ceri Fiddes, said competition questions
>    encouraged "clever thinking rather than regurgitating a taught
>    syllabus".
>    [...]
>    "A lot of Olympiad questions in the competition are about
>    proving things," Dr Fiddes said.
>
>    "If you have a puzzle, it's not good enough to give one answer.
>    You have to prove that it's the only possible answer."
>    [...]
>    "In the Olympiad it's about starting with a problem that anybody
>    could understand, then coming up with that clever idea that
>    enables you to solve it," she said.
>
>    "For example, take the numbers one up to 17.
>
>    "Can you write them out in a line so that every pair of numbers
>    that are next to each other, adds up to give a square number?"
>
> Well, that's the challenge: Write (from scratch) an R program
> that solves this problem. And make it neat.
>
> NOTE: If there should happen to be some R package that can solve
> this kind of problem already, without you having to think much,
> then its use is illegitimate! (I.e. will be deemed "regurgitation").
>
> Over to you.
>
> With best wishes,
> Ted.
>
> -------------------------------------------------
> E-Mail: (Ted Harding)<Ted.Harding at wlandres.net>
> Date: 13-Apr-2012  Time: 22:33:43
> This message was sent by XFMail
>
> ______________________________________________
> R-help at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
>
>



More information about the R-help mailing list