Determine if a string is collapsible

Determine if a character string is   ''collapsible''.

And if so,   collapse the string   (by removing   ''immediately repeated''   characters).

If a character string has   ''immediately repeated''   character(s),   the repeated characters are to be
deleted (removed),   but not the primary (1st) character(s).

An   ''immediately repeated''   character is any character that is   immediately   followed by an
identical character (or characters).   Another word choice could've been   ''duplicated character'',   but that
might have ruled out   (to some readers)   triplicated characters   ***   or more.

{This Rosetta Code task was inspired by a newly introduced   (as of around November 2019)   '''PL/I'''   BIF:   '''collapse'''.}

;Examples:
In the following character string:

  The better the 4-wheel drive, the further you'll be from help when ya get stuck!

Only the 2nd   '''t''',   '''e''', and   '''l'''   are repeated characters,   indicated
by underscores (above),   even though they (those characters) appear elsewhere in the character string.

So, after ''collapsing'' the string, the result would be:

  The beter the 4-whel drive, the further you'l be from help when ya get stuck!

Another example:
In the following character string:

  headmistressship

The "collapsed" string would be:

  headmistreship

;Task:
Write a subroutine/function/procedure/routine***   to
locate   ''repeated''   characters and   ''collapse''   (delete)   them from the character
string.   The character string can be processed from either direction.

Show all output here, on this page:
:*   the   original string and its length
:*   the       resultant string and its length
:*   the above strings should be "bracketed" with   '''<<<'''   and   '''>>>'''   (to delineate blanks)
;*   <<<<<<Guillemets may be used instead for "bracketing" for the more artistic programmers,   shown used here>>>>>>

Use (at least) the following five strings,   all strings are length seventy-two (characters, including blanks),   except
the 1st string:

  string
  number
         ++
    1    |+-----------------------------------------------------------------------+   <######  a null string  (length zero)
    2    |"If I were two-faced, would I be wearing this one?" --- Abraham Lincoln |
    3    |..1111111111111111111111111111111111111111111111111111111111111117777888|
    4    |I never give 'em hell, I just tell the truth, and they think it's hell. |
    5    |                                                    --- Harry S Truman  |   <######  has many repeated blanks
         +------------------------------------------------------------------------+

Solution:
strings = ["",
        '"If I were two-faced, would I be wearing this one?" --- Abraham Lincoln ',
        "..1111111111111111111111111111111111111111111111111111111111111117777888",
        "I never give 'em hell, I just tell the truth, and they think it's hell. ",
        "                                                   ---  Harry S Truman  ",
        "The better the 4-wheel drive, the further you'll be from help when ya get stuck!",
        "headmistressship",
        "aardvark",
        "😍😀🙌💃😍😍😍🙌",]

strings.each do |str|
  puts "«««#{str}»»» (size #{str.size})"
  ssq = str.squeeze
  puts "«««#{ssq}»»» (size #{ssq.size})"
  puts
end


Determine if a string is squeezable

Determine if a character string is   ''squeezable''.

And if so,   squeeze the string   (by removing any number of
a   ''specified''   ''immediately repeated''   character).

This task is very similar to the task     '''Determine if a character string is collapsible'''     except
that only a specified character is   ''squeezed''   instead of any character that is ''immediately repeated''.

If a character string has a specified   ''immediately repeated''   character(s),   the repeated characters are to be
deleted (removed),   but not the primary (1st) character(s).

A specified   ''immediately repeated''   character is any specified character that is   immediately
followed by an identical character (or characters).   Another word choice could've been   ''duplicated
character'',   but that might have ruled out   (to some readers)   triplicated characters   ***   or more.

{This Rosetta Code task was inspired by a newly introduced   (as of around
November 2019)   '''PL/I'''   BIF:   '''squeeze'''.}

;Examples:
In the following character string with a specified   ''immediately repeated''   character of   '''e''':

  The better the 4-wheel drive, the further you'll be from help when ya get stuck!

Only the 2nd   '''e'''   is an specified repeated character,   indicated by an underscore
(above),   even though they (the characters) appear elsewhere in the character string.

So, after ''squeezing'' the string, the result would be:

  The better the 4-whel drive, the further you'll be from help when ya get stuck!

Another example:
In the following character string,   using a specified immediately repeated character   '''s''':

  headmistressship

The "squeezed" string would be:

  headmistreship

;Task:
Write a subroutine/function/procedure/routine***   to locate a   ''specified immediately repeated''   character
and   ''squeeze''   (delete)   them from the character string.   The
character string can be processed from either direction.

Show all output here, on this page:
:*   the   specified repeated character   (to be searched for and possibly ''squeezed''):
:*   the   original string and its length
:*   the       resultant string and its length
:*   the above strings should be "bracketed" with   '''<<<'''   and   '''>>>'''   (to delineate blanks)
;*   <<<<<<Guillemets may be used instead for "bracketing" for the more artistic programmers,   shown used here>>>>>>

Use (at least) the following five strings,   all strings are length seventy-two (characters, including blanks),   except
the 1st string:

                                                                                immediately
  string                                                                            repeated
  number                                                                            character
                                                                                ( |   a blank,  a minus,  a seven,  a period)
         ++
    1    |+-----------------------------------------------------------------------+    ' '    <######  a null string  (length zero)
    2    |"If I were two-faced, would I be wearing this one?" --- Abraham Lincoln |    '-'
    3    |..1111111111111111111111111111111111111111111111111111111111111117777888|    '7'
    4    |I never give 'em hell, I just tell the truth, and they think it's hell. |    '.'
    5    |                                                    --- Harry S Truman  |  (below)  <######  has many repeated blanks
         +------------------------------------------------------------------------+     |
                                                                                |
                                                                                |
         For the 5th string  (Truman's signature line),  use each of these  specified immediately  repeated characters:
                                   *  a blank
                                   *  a minus
                                   *  a lowercase  '''r'''

Note:   there should be seven results shown,   one each for the 1st four strings,   and three results for
the 5th string.

Solution:
strings = ["",
        '"If I were two-faced, would I be wearing this one?" --- Abraham Lincoln ',
        "..1111111111111111111111111111111111111111111111111111111111111117777888",
        "I never give 'em hell, I just tell the truth, and they think it's hell. ",
        "                                                   ---  Harry S Truman  ",
        "😍😀🙌💃😍😍😍🙌",]
squeeze_these = ["", "-", "7", ".", " -r", "😍"]

strings.zip(squeeze_these).each do |str, st|
  puts "original:     «««#{str}»»» (size #{str.size})"
  st.chars.each do |c|
    ssq = str.squeeze(c)
    puts "#{c.inspect}-squeezed: «««#{ssq}»»» (size #{ssq.size})"
  end
  puts
end


Determine if two triangles overlap

Solution:
require "matrix"

def det2D(p1, p2, p3)
    return p1[0] * (p2[1] - p3[1]) + p2[0] * (p3[1] - p1[1]) + p3[0] * (p1[1] - p2[1])
end

def checkTriWinding(p1, p2, p3, allowReversed)
    detTri = det2D(p1, p2, p3)
    if detTri < 0.0 then
        if allowReversed then
            p2[0], p3[0] = p3[0], p2[0]
            p2[1], p3[1] = p3[1], p2[1]
        else
            raise "Triangle has incorrect winding"
        end
    end
end

def boundaryCollideChk(p1, p2, p3, eps)
    return det2D(p1, p2, p3) < eps
end

def boundaryDoesntCollideChk(p1, p2, p3, eps)
    return det2D(p1, p2, p3) <= eps
end

def triTri2D(t1, t2, eps, allowReversed, onBoundary)
    # Triangles must be expressed anti-clockwise
    checkTriWinding(t1[0], t1[1], t1[2], allowReversed)
    checkTriWinding(t2[0], t2[1], t2[2], allowReversed)

    if onBoundary then
        # Points on the boundary are considered as colliding
        chkEdge = -> (p1, p2, p3, eps) { boundaryCollideChk(p1, p2, p3, eps) }
    else
        # Points on the boundary are not considered as colliding
        chkEdge = -> (p1, p2, p3, eps) { boundaryDoesntCollideChk(p1, p2, p3, eps) }
    end

    # For edge E of triangle 1
    for i in 0..2 do
        j = (i + 1) % 3

        # Check all points of trangle 2 lay on the external side of the edge E. If
        # they do, the triangles do not collide.
        if chkEdge.(t1[i], t1[j], t2[0], eps) and chkEdge.(t1[i], t1[j], t2[1], eps) and chkEdge.(t1[i], t1[j], t2[2], eps) then
            return false
        end
    end

    # For edge E of triangle 2
    for i in 0..2 do
        j = (i + 1) % 3

        # Check all points of trangle 1 lay on the external side of the edge E. If
        # they do, the triangles do not collide.
        if chkEdge.(t2[i], t2[j], t1[0], eps) and chkEdge.(t2[i], t2[j], t1[1], eps) and chkEdge.(t2[i], t2[j], t1[2], eps) then
            return false
        end
    end

    # The triangles collide
    return true
end

def main
    t1 = [Vector[0,0], Vector[5,0], Vector[0,5]]
    t2 = [Vector[0,0], Vector[5,0], Vector[0,6]]
    print "Triangle: ", t1, "\n"
    print "Triangle: ", t2, "\n"
    print "overlap: %s\n\n" % [triTri2D(t1, t2, 0.0, false, true)]

    t1 = [Vector[0,0], Vector[0,5], Vector[5,0]]
    t2 = [Vector[0,0], Vector[0,5], Vector[5,0]]
    print "Triangle: ", t1, "\n"
    print "Triangle: ", t2, "\n"
    print "overlap: %s\n\n" % [triTri2D(t1, t2, 0.0, true, true)]

    t1 = [Vector[  0,0], Vector[ 5,0], Vector[ 0,5]]
    t2 = [Vector[-10,0], Vector[-5,0], Vector[-1,6]]
    print "Triangle: ", t1, "\n"
    print "Triangle: ", t2, "\n"
    print "overlap: %s\n\n" % [triTri2D(t1, t2, 0.0, false, true)]

    t1 = [Vector[0,0], Vector[  5, 0], Vector[2.5,5]]
    t2 = [Vector[0,4], Vector[2.5,-1], Vector[  5,4]]
    print "Triangle: ", t1, "\n"
    print "Triangle: ", t2, "\n"
    print "overlap: %s\n\n" % [triTri2D(t1, t2, 0.0, false, true)]

    t1 = [Vector[0,0], Vector[1,1], Vector[0,2]]
    t2 = [Vector[2,1], Vector[3,0], Vector[3,2]]
    print "Triangle: ", t1, "\n"
    print "Triangle: ", t2, "\n"
    print "overlap: %s\n\n" % [triTri2D(t1, t2, 0.0, false, true)]

    t1 = [Vector[0,0], Vector[1, 1], Vector[0,2]]
    t2 = [Vector[2,1], Vector[3,-2], Vector[3,4]]
    print "Triangle: ", t1, "\n"
    print "Triangle: ", t2, "\n"
    print "overlap: %s\n\n" % [triTri2D(t1, t2, 0.0, false, true)]

    # Barely touching
    t1 = [Vector[0,0], Vector[1,0], Vector[0,1]]
    t2 = [Vector[1,0], Vector[2,0], Vector[1,1]]
    print "Triangle: ", t1, "\n"
    print "Triangle: ", t2, "\n"
    print "overlap: %s\n\n" % [triTri2D(t1, t2, 0.0, false, true)]

    # Barely touching
    t1 = [Vector[0,0], Vector[1,0], Vector[0,1]]
    t2 = [Vector[1,0], Vector[2,0], Vector[1,1]]
    print "Triangle: ", t1, "\n"
    print "Triangle: ", t2, "\n"
    print "overlap: %s\n\n" % [triTri2D(t1, t2, 0.0, false, false)]
end

main()


Dice game probabilities

Two players have a set of dice each. The first player has nine dice with four faces each, with numbers one to four. The second player has six normal dice with six faces each, each face has the usual numbers from one to six.

They roll their dice and sum the totals of the faces. The player with the highest total wins (it's a draw if the totals are the same). What's the probability of the first player beating the second player?

Later the two players use a different set of dice each. Now the first player has five dice with ten faces each, and the second player has six dice with seven faces each. Now what's the probability of the first player beating the second player?

This task was adapted from the Project Euler Problem n.205:
https://projecteuler.net/problem=205

Solution:
def roll_dice(n_dice, n_faces)
  return [[0,1]] if n_dice.zero?
  one  = [1] * n_faces
  zero = [0] * (n_faces-1)
  (1...n_dice).inject(one){|ary,_|
    (zero + ary + zero).each_cons(n_faces).map{|a| a.inject(:+)}
  }.map.with_index(n_dice){|n,sum| [sum,n]}  # sum: total of the faces
end

def game(dice1, faces1, dice2, faces2)
  p1 = roll_dice(dice1, faces1)
  p2 = roll_dice(dice2, faces2)
  p1.product(p2).each_with_object([0,0,0]) do |((sum1, n1), (sum2, n2)), win|
    win[sum1 <=> sum2] += n1 * n2        # [0]:draw, [1]:win, [-1]:lose
  end
end

[[9, 4, 6, 6], [5, 10, 6, 7]].each do |d1, f1, d2, f2|
  puts "player 1 has #{d1} dice with #{f1} faces each"
  puts "player 2 has #{d2} dice with #{f2} faces each"
  win = game(d1, f1, d2, f2)
  sum = win.inject(:+)
  puts "Probability for player 1 to win: #{win[1]} / #{sum}",
       "                              -> #{win[1].fdiv(sum)}", ""
end


Digital root

The digital root, X, of a number, n, is calculated:
: find X as the sum of the digits of n
: find a new X by summing the digits of X, repeating until X has only one digit.

The additive persistence is the number of summations required to obtain the single digit.

The task is to calculate the additive persistence and the digital root of a number, e.g.:
:627615 has additive persistence 2 and digital root of 9;
:39390 has additive persistence 2 and digital root of 6;
:588225 has additive persistence 2 and digital root of 3;
:393900588225 has additive persistence 2 and digital root of 9;

The digital root may be calculated in bases other than 10.

;See:
* [[Casting out nines]] for this wiki's use of this procedure.
* [[Digital root/Multiplicative digital root]]
* [[Sum digits of an integer]]
* Digital root sequence on OEIS
* Additive persistence sequence on OEIS
* [[Iterated digits squaring]]

Solution:
class String
  def digroot_persistence(base=10)
    num = self.to_i(base)
    persistence = 0
    until num < base do
      num = num.digits(base).sum
      persistence += 1
    end
    [num.to_s(base), persistence]
  end
end

puts "--- Examples in 10-Base ---"
%w(627615 39390 588225 393900588225).each do |str|
  puts "%12s has a digital root of %s and a persistence of %s." % [str, *str.digroot_persistence]
end
puts "\n--- Examples in other Base ---"
format = "%s base %s has a digital root of %s and a persistence of %s."
[["101101110110110010011011111110011000001", 2],
 [ "5BB64DFCC1", 16],
 ["5", 8],
 ["50YE8N29", 36]].each do |(str, base)|
   puts format % [str, base, *str.digroot_persistence(base)]
end


Disarium numbers

A '''Disarium number''' is an integer where the sum of each digit raised to the power of its position in the number, is equal to the number.

;E.G.

'''135''' is a '''Disarium number''':

 11 + 32 + 53 == 1 + 9 + 125 == 135

There are a finite number of '''Disarium numbers'''.

;Task

* Find and display the first 18 '''Disarium numbers'''.

;Stretch

* Find and display all 20 '''Disarium numbers'''.

;See also

;* Geeks for Geeks - Disarium numbers
;* OEIS:A032799 - Numbers n such that n equals the sum of its digits raised to the consecutive powers (1,2,3,...)
;* Related task: Narcissistic decimal number
;* Related task: Own digits power sum  ''Which seems to be the same task as Narcissistic decimal number...''

Solution:
disariums = Enumerator.new do |y|
  (0..).each do |n|
    i = 0
    y << n if n.digits.reverse.sum{|d| d ** (i+=1) } == n
  end
end

puts disariums.take(19).to_a.join(" ")


Display a linear combination

Display a finite linear combination in an infinite vector basis (e_1, e_2,\ldots).

Write a function that, when given a finite list of scalars (\alpha^1,\alpha^2,\ldots), creates a string representing the linear combination \sum_i\alpha^i e_i in an explicit format often used in mathematics, that is:

:\alpha^{i_1}e_{i_1}\pm|\alpha^{i_2}|e_{i_2}\pm|\alpha^{i_3}|e_{i_3}\pm\ldots

where \alpha^{i_k}\neq 0

The output must comply to the following rules:
*   don't show null terms, unless the whole combination is null.
:::::::  '''e(1)'''     is fine,     '''e(1) + 0*e(3)'''     or     '''e(1) + 0'''     is wrong.
*   don't show scalars when they are equal to one or minus one.
:::::::  '''e(3)'''     is fine,     '''1*e(3)'''     is wrong.
*   don't prefix by a minus sign if it follows a preceding term.   Instead you use subtraction.
:::::::  '''e(4) - e(5)'''     is fine,     '''e(4) + -e(5)'''     is wrong.

Show here output for the following lists of scalars:

 1)    1,  2,  3
 2)    0,  1,  2,  3
 3)    1,  0,  3,  4
 4)    1,  2,  0
 5)    0,  0,  0
 6)    0
 7)    1,  1,  1
 8)   -1, -1, -1
 9)   -1, -2,  0, -3
10)   -1

Solution:
def linearCombo(c)
    sb = ""
    c.each_with_index { |n, i|
        if n == 0 then
            next
        end
        if n < 0 then
            if sb.length == 0 then
                op = "-"
            else
                op = " - "
            end
        elsif n > 0 then
            if sb.length > 0 then
                op = " + "
            else
                op = ""
            end
        else
            op = ""
        end
        av = n.abs()
        if av != 1 then
            coeff = "%d*" % [av]
        else
            coeff = ""
        end
        sb = sb + "%s%se(%d)" % [op, coeff, i + 1]
    }
    if sb.length == 0 then
        return "0"
    end
    return sb
end

def main
    combos = [
        [1, 2, 3],
        [0, 1, 2, 3],
        [1, 0, 3, 4],
        [1, 2, 0],
        [0, 0, 0],
        [0],
        [1, 1, 1],
        [-1, -1, -1],
        [-1, -2, 0, -3],
        [-1],
    ]

    for c in combos do
        print "%-15s  ->  %s\n" % [c, linearCombo(c)]
    end
end

main()


Distance and Bearing

It is very important in aviation to have knowledge of the nearby airports at any time in flight.
;Task:
Determine the distance and bearing from an Airplane to the 20 nearest Airports whenever requested.
Use the non-commercial data from openflights.org airports.dat as reference.

A request comes from an airplane at position  ( latitude, longitude ): ( '''51.514669, 2.198581''' ).

Your report should contain the following information from table airports.dat (column shown in brackets):

Name(2), Country(4), ICAO(6), Distance and Bearing calculated from Latitude(7) and Longitude(8).

Distance is measured in nautical miles (NM). Resolution is 0.1 NM.

Bearing is measured in degrees (deg). 0deg = 360deg = north then clockwise 90deg = east, 180deg = south, 270deg = west. Resolution is 1deg.

;See:
:*   openflights.org/data:  Airport, airline and route data
:*   Movable Type Scripts:  Calculate distance, bearing and more between Latitude/Longitude points

Solution:
require 'open-uri'
require 'csv'
include Math

RADIUS = 6372.8  # rough radius of the Earth, in kilometers

def spherical_distance(start_coords, end_coords)
  lat1, long1 = deg2rad(*start_coords)
  lat2, long2 = deg2rad(*end_coords)
  2 * RADIUS * asin(sqrt(sin((lat2-lat1)/2)**2 + cos(lat1) * cos(lat2) * sin((long2 - long1)/2)**2))
end

def bearing(start_coords, end_coords)
  lat1, long1 = deg2rad(*start_coords)
  lat2, long2 = deg2rad(*end_coords)
  dlon = long2 - long1
  atan2(sin(dlon) * cos(lat2), cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dlon))
end

def deg2rad(lat, long)
  [lat * PI / 180, long * PI / 180]
end

uri = "https://raw.githubusercontent.com/jpatokal/openflights/master/data/airports.dat"
headers = %i(airportID
    name
    city
    country
    iata
    icao
    latitude
    longitude
    altitude
    timezone
    dst
    tzOlson
    type
    source)
data = CSV.parse(URI.open(uri), headers: headers, converters: :numeric)

position = [51.514669, 2.198581]

data.each{|r| r[:dist] = (spherical_distance(position, [r[:latitude], r[:longitude]])/1.852).round(1)}
closest =  data.min_by(20){|row| row[:dist] }
closest.each do |r|
  bearing = (bearing(position,[r[:latitude], r[:longitude]])*180/PI).round % 360
  puts "%-40s %-25s %-6s %12.1f %15.0f" % (r.values_at(:name, :country, :ICAO, :dist) << bearing)
end


Diversity prediction theorem

The   ''wisdom of the crowd''   is the collective opinion of a group of individuals rather than that of a single expert.

Wisdom-of-the-crowds research routinely attributes the superiority of crowd averages over individual judgments to the elimination of individual noise,   an explanation that assumes independence of the individual judgments from each other.

Thus the crowd tends to make its best decisions if it is made up of diverse opinions and ideologies.

Scott E. Page introduced the diversity prediction theorem:
: ''The squared error of the collective prediction equals the average squared error minus the predictive diversity''.

Therefore,   when the diversity in a group is large,   the error of the crowd is small.

;Definitions:
::*   Average Individual Error:   Average of the individual squared errors
::*   Collective Error:           Squared error of the collective prediction
::*   Prediction Diversity:       Average squared distance from the individual predictions to the collective prediction
::*   Diversity Prediction Theorem:   ''Given a crowd of predictive models'',     then
::::::   Collective Error   =   Average Individual Error   -   Prediction Diversity

;Task:
For a given   true   value and a number of number of estimates (from a crowd),   show   (here on this page):
:::*   the true value   and   the crowd estimates
:::*   the average error
:::*   the crowd error
:::*   the prediction diversity

Use   (at least)   these two examples:
:::*   a true value of   '''49'''   with crowd estimates of:   ''' 48   47   51'''
:::*   a true value of   '''49'''   with crowd estimates of:   ''' 48   47   51   42'''

;Also see:
:*   Wikipedia entry:   Wisdom of the crowd
:*   University of Michigan: PDF paper         (exists on a web archive,   the ''Wayback Machine'').

Solution:
def mean(a) = a.sum(0.0) / a.size
def mean_square_diff(a, predictions) = mean(predictions.map { |x| square(x - a)**2 })

def diversity_theorem(truth, predictions)
    average = mean(predictions)
    puts "truth: #{truth}, predictions #{predictions}",
         "average-error: #{mean_square_diff(truth, predictions)}",
         "crowd-error: #{(truth - average)**2}",
         "diversity: #{mean_square_diff(average, predictions)}",""
end

diversity_theorem(49.0, [48.0, 47.0, 51.0])
diversity_theorem(49.0, [48.0, 47.0, 51.0, 42.0])


Dot product

Create a function/use an in-built function, to compute the   '''dot product''',   also known as the   '''scalar product'''   of two vectors.

If possible, make the vectors of arbitrary length.

As an example, compute the dot product of the vectors:
::::     [1,  3, -5]       and
::::     [4,      -2, -1]

If implementing the dot product of two vectors directly:
:::*   each vector must be the same length
:::*   multiply corresponding terms from each vector
:::*   sum the products   (to produce the answer)

;Related task:
*   [[Vector products]]

Solution:
class Array
  def dot_product(other)
    raise "not the same size!" if self.length != other.length
    zip(other).sum {|a, b| a*b}
  end
end

p [1, 3, -5].dot_product [4, -2, -1]   # => 3


Dutch national flag problem

The Dutch national flag is composed of three coloured bands in the order:
::*   red     (top)
::*   then white,   and
::*   lastly blue   (at the bottom).

The problem posed by Edsger Dijkstra is:
:Given a number of red, blue and white balls in random order, arrange them in the order of the colours in the Dutch national flag.
When the problem was first posed, Dijkstra then went on to successively refine a solution, minimising the number of swaps and the number of times the colour of a ball needed to determined and restricting the balls to end in an array, ...

;Task
# Generate a randomized order of balls ''ensuring that they are not in the order of the Dutch national flag''.
# Sort the balls in a way idiomatic to your language.
# Check the sorted balls ''are'' in the order of the Dutch national flag.

;C.f.:
* Dutch national flag problem
* Probabilistic analysis of algorithms for the Dutch national flag problem by Wei-Mei Chen. (pdf)

Solution:
class Ball
  FLAG = {red: 1, white: 2, blue: 3}

  def initialize
    @color = FLAG.keys.sample
  end

  def color
    @color
  end

  def <=>(other)  # needed for sort, results in -1 for <, 0 for == and 1 for >.
    FLAG[self.color] <=> FLAG[other.color]
  end

  def inspect
    @color
  end
end

balls = []
balls = Array.new(8){Ball.new} while balls == balls.sort

puts "Random: #{balls}"
puts "Sorted: #{balls.sort}"


Eban numbers

Definition:
An   '''eban'''   number is a number that has no letter    '''e'''    in it when the number is spelled in English.

Or more literally,   spelled numbers that contain the letter   '''e'''   are banned.

The American version of spelling numbers will be used here   (as opposed to the British).

'''2,000,000,000'''   is two billion,   ''not''   two milliard.

Only numbers less than   '''one sextillion'''   ('''1021''')   will be considered in/for this task.

This will allow optimizations to be used.

;Task:
:::*   show all eban numbers   <=   '''1,000'''   (in a horizontal format),                   and a count
:::*   show all eban numbers between   '''1,000'''   and   '''4,000'''   (inclusive),   and a count
:::*   show a count of all eban numbers up and including            '''10,000'''
:::*   show a count of all eban numbers up and including                '''100,000'''
:::*   show a count of all eban numbers up and including                   '''1,000,000'''
:::*   show a count of all eban numbers up and including                      '''10,000,000'''
:::*   show all output here.

;See also:
:*   The MathWorld entry:    eban numbers.
:*   The OEIS      entry:   A6933,                eban numbers.
:*   [[Number names]].

Solution:
def main
    intervals = [
        [2, 1000, true],
        [1000, 4000, true],
        [2, 10000, false],
        [2, 100000, false],
        [2, 1000000, false],
        [2, 10000000, false],
        [2, 100000000, false],
        [2, 1000000000, false]
    ]
    for intv in intervals
        (start, ending, display) = intv
        if start == 2 then
            print "eban numbers up to and including %d:\n" % [ending]
        else
            print "eban numbers between %d and %d (inclusive):\n" % [start, ending]
        end

        count = 0
        for i in (start .. ending).step(2)
            b = (i / 1000000000).floor
            r = (i % 1000000000)
            m = (r / 1000000).floor
            r = (r % 1000000)
            t = (r / 1000).floor
            r = (r % 1000)
            if m >= 30 and m <= 66 then
                m = m % 10
            end
            if t >= 30 and t <= 66 then
                t = t % 10
            end
            if r >= 30 and r <= 66 then
                r = r % 10
            end
            if b == 0 or b == 2 or b == 4 or b == 6 then
                if m == 0 or m == 2 or m == 4 or m == 6 then
                    if t == 0 or t == 2 or t == 4 or t == 6 then
                        if r == 0 or r == 2 or r == 4 or r == 6 then
                            if display then
                                print ' ', i
                            end
                            count = count + 1
                        end
                    end
                end
            end
        end
        if display then
            print "\n"
        end
        print "count = %d\n\n" % [count]
    end
end

main()


Eertree

An '''eertree''' is a data structure designed for efficient processing of certain palindrome tasks, for instance counting the number of sub-palindromes in an input string.

The data structure has commonalities to both ''tries'' and ''suffix trees''.
  See links below.

;Task:
Construct an eertree for the string "eertree", then output all sub-palindromes by traversing the tree.

;See also:
*   Wikipedia entry:   trie.
*   Wikipedia entry:   suffix tree
*   Cornell University Library, Computer Science, Data Structures and Algorithms ---> EERTREE: An Efficient Data Structure for Processing Palindromes in Strings.

Solution:
class Node
    def initialize(length, edges = {}, suffix = 0)
        @length = length
        @edges = edges
        @suffix = suffix
    end

    attr_reader :length
    attr_reader :edges
    attr_accessor :suffix
end

EVEN_ROOT = 0
ODD_ROOT = 1

def eertree(s)
    tree = [
        Node.new(0, {}, ODD_ROOT),
        Node.new(-1, {}, ODD_ROOT)
    ]
    suffix = ODD_ROOT
    s.each_char.with_index { |c, i|
        n = suffix
        k = 0
        loop do
            k = tree[n].length
            b = i - k - 1
            if b >= 0 and s[b] == c then
                break
            end
            n = tree[n].suffix
        end
        if tree[n].edges.key?(c) then
                suffix = tree[n].edges[c]
            next
        end
        suffix = tree.length
        tree << Node.new(k + 2)
        tree[n].edges[c] = suffix
        if tree[suffix].length == 1 then
            tree[suffix].suffix = 0
            next
        end
        loop do
            n = tree[n].suffix
            b = i - tree[n].length - 1
            if b >= 0 and s[b] == c then
                break
            end
        end
        tree[suffix].suffix = tree[n].edges[c]
    }
    return tree
end

def subPalindromes(tree)
    s = []

    children = lambda { |n,p,f|
        for c,v in tree[n].edges
            m = tree[n].edges[c]
            p = c + p + c
            s << p
            f.call(m, p, f)
        end
    }

    children.call(0, '', children)

    for c,n in tree[1].edges
        s << c
        children.call(n, c, children)
    end

    return s
end

tree = eertree("eertree")
print subPalindromes(tree), "\n"


Egyptian division

Egyptian division is a method of dividing integers using addition and
doubling that is similar to the algorithm of [[Ethiopian multiplication]]

'''Algorithm:'''

Given two numbers where the '''dividend''' is to be divided by the '''divisor''':

# Start the construction of a table of two columns: '''powers_of_2''', and '''doublings'''; by a first row of a 1 (i.e. 2^0) in the first column and 1 times the divisor in the first row second column.
# Create the second row with columns of 2 (i.e 2^1), and 2 * divisor in order.
# Continue with successive i'th rows of 2^i and 2^i * divisor.
# Stop adding rows, and keep only those rows, where 2^i * divisor is less than or equal to the dividend.
# We now assemble two separate sums that both start as zero, called here '''answer''' and '''accumulator'''
# Consider each row of the table, in the ''reverse'' order of its construction.
# If the current value of the accumulator added to the doublings cell would be less than or equal to the dividend then add it to the accumulator, as well as adding the powers_of_2 cell value to the answer.
# When the first row has been considered as above, then the integer division of dividend by divisor is given by answer. (And the remainder is given by the absolute value of accumulator - dividend).

'''Example: 580 / 34'''

''' Table creation: '''

::: {| class="wikitable"
! powers_of_2
! doublings
|-
| 1
| 34
|-
| 2
| 68
|-
| 4
| 136
|-
| 8
| 272
|-
| 16
| 544
|}

''' Initialization of sums: '''

::: {| class="wikitable"
! powers_of_2
! doublings
! answer
! accumulator
|-
| 1
| 34
|

|

|-
| 2
| 68
|

|

|-
| 4
| 136
|

|

|-
| 8
| 272
|

|

|-
| 16
| 544
|

|

|-
|
|
| 0
| 0
|}

''' Considering table rows, bottom-up: '''

When a row is considered it is shown crossed out if it is not accumulated, or '''bold''' if the row causes summations.

::: {| class="wikitable"
! powers_of_2
! doublings
! answer
! accumulator
|-
| 1
| 34
|

|

|-
| 2
| 68
|

|

|-
| 4
| 136
|

|

|-
| 8
| 272
|

|

|-
| '''16'''
| '''544'''
| 16
| 544
|}

::: {| class="wikitable"
! powers_of_2
! doublings
! answer
! accumulator
|-
| 1
| 34
|

|

|-
| 2
| 68
|

|

|-
| 4
| 136
|

|

|-
| 8
| 272
| 16
| 544
|-
| '''16'''
| '''544'''
|

|

|}

::: {| class="wikitable"
! powers_of_2
! doublings
! answer
! accumulator
|-
| 1
| 34
|

|

|-
| 2
| 68
|

|

|-
| 4
| 136
| 16
| 544
|-
| 8
| 272
|

|

|-
| '''16'''
| '''544'''
|

|

|}

::: {| class="wikitable"
! powers_of_2
! doublings
! answer
! accumulator
|-
| 1
| 34
|

|

|-
| 2
| 68
| 16
| 544
|-
| 4
| 136
|

|

|-
| 8
| 272
|

|

|-
| '''16'''
| '''544'''
|

|

|}

::: {| class="wikitable"
! powers_of_2
! doublings
! answer
! accumulator
|-
| '''1'''
| '''34'''
| 17
| 578
|-
| 2
| 68
|

|

|-
| 4
| 136
|

|

|-
| 8
| 272
|

|

|-
| '''16'''
| '''544'''
|

|

|}

;Answer:
So 580 divided by 34 using the Egyptian method is '''17''' remainder (578 - 580) or '''2'''.

;Task:
The task is to create a function that does Egyptian division. The function should
closely follow the description above in using a list/array of powers of two, and
another of doublings.

* Functions should be clear interpretations of the algorithm.
* Use the function to divide 580 by 34 and show the answer '''here, on this page'''.

;Related tasks:
:*   Egyptian fractions

;References:
:*   Egyptian Number System

Solution:
def egyptian_divmod(dividend, divisor)
  table = [[1, divisor]]
  table << table.last.map{|e| e*2} while table.last.first * 2 <= dividend
  answer, accumulator = 0, 0
  table.reverse_each do |pow, double|
    if accumulator + double <= dividend
      accumulator += double
      answer += pow
    end
  end
  [answer, dividend - accumulator]
end

puts "Quotient = %s Remainder = %s" % egyptian_divmod(580, 34)


Elementary cellular automaton

An '''cellular automaton where there are two possible states (labeled 0 and 1) and the rule to determine the state of a cell in the next generation depends only on the current state of the cell and its two immediate neighbors.  Those three values can be encoded with three bits.

The rules of evolution are then encoded with eight bits indicating the outcome of each of the eight possibilities 111, 110, 101, 100, 011, 010, 001 and 000 in this order.  Thus for instance the rule 13 means that a state is updated to 1 only in the cases 011, 010 and 000, since 13 in binary is 0b00001101.

;Task:
Create a subroutine, program or function that allows to create and visualize the evolution of any of the 256 possible elementary cellular automaton of arbitrary space length and for any given initial state.  You can demonstrate your solution with any automaton of your choice.

The space state should ''wrap'':  this means that the left-most cell should be considered as the right neighbor of the right-most cell, and reciprocally.

This task is basically a generalization of [[one-dimensional cellular automata]].

;See also
* Cellular automata (natureofcode.com)

Solution:
class ElemCellAutomat
  include Enumerable

  def initialize (start_str, rule, disp=false)
    @cur = start_str
    @patterns = Hash[8.times.map{|i|["%03b"%i, "01"[rule[i]]]}]
    puts "Rule (#{rule}) : #@patterns" if disp
  end

  def each
    return to_enum unless block_given?
    loop do
      yield @cur
      str = @cur[-1] + @cur + @cur[0]
      @cur = @cur.size.times.map {|i| @patterns[str[i,3]]}.join
    end
  end

end

eca = ElemCellAutomat.new('1'.center(39, "0"), 18, true)
eca.take(30).each{|line| puts line.tr("01", ".#")}


Elementary cellular automaton/Infinite length

The purpose of this task is to create a version of an [[Elementary cellular automaton]] whose number of cells is only limited by the memory size of the computer.

To be precise, consider the state of the automaton to be made of an infinite number of cells, but with a bounded support.  In other words, to describe the state of the automaton, you need a finite number of adjacent cells, along with their individual state, and you then consider that the individual state of each of all other cells is the negation of the closest individual cell among the previously defined finite number of cells.

Examples:

1        ->   ..., 0, 0,      1,      0, 0, ...
0, 1     ->   ..., 1, 1,   0, 1,      0, 0, ...
1, 0, 1  ->   ..., 0, 0,   1, 0, 1,   0, 0, ...

More complex methods can be imagined, provided it is possible to somehow encode the infinite sections.  But for this task we will stick to this simple version.

Solution:
def notcell(c)
  c.tr('01','10')
end

def eca_infinite(cells, rule)
  neighbours2next = Hash[8.times.map{|i|["%03b"%i, "01"[rule[i]]]}]
  c = cells
  Enumerator.new do |y|
    loop do
      y << c
      c = notcell(c[0])*2 + c + notcell(c[-1])*2        # Extend and pad the ends
      c = (1..c.size-2).map{|i| neighbours2next[c[i-1..i+1]]}.join
    end
  end
end

if __FILE__ == $0
  lines = 25
  for rule in [90, 30]
    puts "\nRule: %i" % rule
    for i, c in (0...lines).zip(eca_infinite('1', rule))
      puts '%2i: %s%s' % [i, ' '*(lines - i), c.tr('01', '.#')]
    end
  end
end


Elementary cellular automaton/Random number generator

Mathematica software for its default random number generator.

Steven Wolfram's recommendation for random number generation from rule 30 consists in extracting successive bits in a fixed position in the array of cells, as the automaton changes state.

The purpose of this task is to demonstrate this.  With the code written in the most significant.

You can pick which ever length you want for the initial array but it should be visible in the code so that your output can be reproduced with an other language.

For extra-credits, you will make this algorithm run as fast as possible in your language, for instance with an extensive use of bitwise logic.

;Reference:
* Cellular automata: Is Rule 30 random? (PDF).

Solution:
size = 100
eca = ElemCellAutomat.new("1"+"0"*(size-1), 30)
eca.take(80).map{|line| line[0]}.each_slice(8){|bin| p bin.join.to_i(2)}


Empty string

Languages may have features for dealing specifically with empty strings
(those containing no characters).

;Task:
::*   Demonstrate how to assign an empty string to a variable.
::*   Demonstrate how to check that a string is empty.
::*   Demonstrate how to check that a string is not empty.

Solution:
s == ""
s.eql?("")
s.empty?
s.length == 0
s[/\A\z/]

# also silly things like
s.each_char.to_a.empty?


Entropy/Narcissist

Write a computer program that computes and shows its own   [[entropy]].

;Related Tasks:
:*   [[Fibonacci_word]]
:*   [[Entropy]]

Solution:
def entropy(s)
  counts = s.each_char.tally
  size = s.size.to_f
  counts.values.reduce(0) do |entropy, count|
    freq = count / size
    entropy - freq * Math.log2(freq)
  end
end

s = File.read(__FILE__)
p entropy(s)


Equilibrium index

An equilibrium index of a sequence is an index into the sequence such that the sum of elements at lower indices is equal to the sum of elements at higher indices.

For example, in a sequence   A:

:::::   A_0 = -7
:::::   A_1 =  1
:::::   A_2 =  5
:::::   A_3 =  2
:::::   A_4 = -4
:::::   A_5 =  3
:::::   A_6 =  0

3   is an equilibrium index, because:

:::::   A_0 + A_1 + A_2 = A_4 + A_5 + A_6

6   is also an equilibrium index, because:

:::::   A_0 + A_1 + A_2 + A_3 + A_4 + A_5 = 0

(sum of zero elements is zero)

7   is not an equilibrium index, because it is not a valid index of sequence A.

;Task;
Write a function that, given a sequence, returns its equilibrium indices (if any).

Assume that the sequence may be very long.

Solution:
def eq_indices(list)
  result = []
  list.empty? and return result
  final = list.size - 1

  helper = lambda do |left, current, right, index|
    left == right and result << index   # Push index to result?
    index == final and return           # Terminate recursion?
    new = list[index + 1]
    helper.call(left + current, new, right - new, index + 1)
  end
  helper.call 0, list.first, list.drop(1).sum, 0
  result
end


Esthetic numbers

An '''esthetic number''' is a positive integer where every adjacent digit differs from its neighbour by 1.

;E.G.

:* '''12''' is an esthetic number. One and two differ by 1.

:* '''5654''' is an esthetic number. Each digit is exactly 1 away from its neighbour.

:* '''890''' is '''not''' an esthetic number. Nine and zero differ by 9.

These examples are nominally in base 10 but the concept extends easily to numbers in other bases. Traditionally, single digit numbers ''are'' included in esthetic numbers; zero may or may not be. For our purposes, for this task, do not include zero (0) as an esthetic number. Do not include numbers with leading zeros.

Esthetic numbers are also sometimes referred to as stepping numbers.

;Task

:* Write a routine (function, procedure, whatever) to find esthetic numbers in a given base.

:* Use that routine to find esthetic numbers in bases '''2''' through '''16''' and display, here on this page, the esthectic numbers from index '''(base x 4)''' through index '''(base x 6)''', inclusive. (E.G. for base 2: 8th through 12th, for base 6: 24th through 36th, etc.)

:* Find and display, here on this page, the '''base 10''' esthetic numbers with a magnitude between '''1000''' and '''9999'''.

:* Stretch: Find and display, here on this page, the '''base 10''' esthetic numbers with a magnitude between '''1.0e8''' and '''1.3e8'''.

;Related task:
*   numbers with equal rises and falls

;See also:
:;*OEIS A033075 - Positive numbers n such that all pairs of consecutive decimal digits differ by 1
:;*Numbers Aplenty - Esthetic numbers
:;*Geeks for Geeks - Stepping numbers

Solution:
def isEsthetic(n, b)
    if n == 0 then
        return false
    end

    i = n % b
    n2 = (n / b).floor
    while n2 > 0
        j = n2 % b
        if (i - j).abs != 1 then
            return false
        end
        n2 = n2 / b
        i = j
    end
    return true
end

def listEsths(n, n2, m, m2, perLine, all)
    esths = Array.new
    dfs = lambda {|n, m, i|
        if n <= i and i <= m then
            esths << i
        end
        if i == 0 or i > m then
            return
        end
        d = i % 10
        i1 = i * 10 + d - 1
        i2 = i1 + 2
        if d == 0 then
            dfs[n, m, i2]
        elsif d == 9 then
            dfs[n, m, i1]
        else
            dfs[n, m, i1]
            dfs[n, m, i2]
        end
    }

    for i in 0..9
        dfs[n2, m2, i]
    end

    le = esths.length
    print "Base 10: %d esthetic numbers between %d and %d:\n" % [le, n, m]
    if all then
        esths.each_with_index { |esth, idx|
            print "%d " % [esth]
            if (idx + 1) % perLine == 0 then
                print "\n"
            end
        }
        print "\n"
    else
        for i in 0 .. perLine - 1
            print "%d " % [esths[i]]
        end
        print "\n............\n"
        for i in le - perLine .. le - 1
            print "%d " % [esths[i]]
        end
        print "\n"
    end
    print "\n"
end

def main
    for b in 2..16
        print "Base %d: %dth to %dth esthetic numbers:\n" % [b, 4 * b, 6 * b]
        n = 1
        c = 0
        while c < 6 * b
            if isEsthetic(n, b) then
                c = c + 1
                if c >= 4 * b then
                    print "%s " % [n.to_s(b)]
                end
            end
            n = n + 1
        end
        print "\n"
    end
    print "\n"

    listEsths(1000, 1010, 9999, 9898, 16, true)
    listEsths(1e8, 101010101, 13 * 1e7, 123456789, 9, true)
    listEsths(1e11, 101010101010, 13 * 1e10, 123456789898, 7, false)
    listEsths(1e14, 101010101010101, 13 * 1e13, 123456789898989, 5, false)
    listEsths(1e17, 101010101010101010, 13 * 1e16, 123456789898989898, 4, false)
end

main()


Euler's sum of powers conjecture

There is a conjecture in mathematics that held for over two hundred years before it was disproved by the finding of a counterexample in 1966 by Lander and Parkin.

This conjecture is called Euler's sum of powers conjecture and can be stated as such:

:At least k positive kth powers are required to sum to a kth power, except for the trivial case of one kth power: yk = yk.

In 1966, Leon J. Lander and Thomas R. Parkin used a brute-force search on a CDC 6600 computer restricting numbers to those less than 250.

The task consists in writing a program to search for an integer solution of x_0^5 + x_1^5 + x_2^5 + x_3^5 = y^5 where all x_i and y are distinct integers between 0 and 250 (exclusive). Show an answer here.

Related tasks are:
* [[Pythagorean quadruples]].
* [[Pythagorean triples]].

Solution:
power5 = (1..250).each_with_object({}){|i,h| h[i**5]=i}
result = power5.keys.repeated_combination(4).select{|a| power5[a.inject(:+)]}
puts result.map{|a| a.map{|i| "#{power5[i]}**5"}.join(' + ') + " = #{power5[a.inject(:+)]}**5"}


Euler's sum of powers conjecture

Solution:
p5, sum2, max = {}, {}, 250
(1..max).each do |i|
  p5[i**5] = i
  (i..max).each{|j| sum2[i**5 + j**5] = [i,j]}
end

result = {}
sk = sum2.keys.sort
p5.keys.sort.each do |p|
  sk.each do |s|
    break if p <= s
    result[(sum2[s] + sum2[p-s]).sort] = p5[p]  if sum2[p - s]
  end
end
result.each{|k,v| puts k.map{|i| "#{i}**5"}.join(' + ') + " = #{v}**5"}


Even or odd

Test whether an integer is even or odd.

There is more than one way to solve this task:

* Use the even and odd predicates, if the language provides them.
* Check the least significant digit. With binary integers, ''i iff ''i'' is even, or equals 1 iff ''i'' is odd.
* Divide ''i'' by 2. The remainder equals 0 iff ''i'' is even. The remainder equals +1 or -1 iff ''i'' is odd.
* Use modular congruences:
** ''i''  0 (mod 2) iff ''i'' is even.
** ''i''  1 (mod 2) iff ''i'' is odd.

Solution:
print "evens: "
p -5.upto(5).select(&:even?)
print "odds: "
p -5.upto(5).select(&:odd?)


Evolutionary algorithm

Starting with:
* The target string: "METHINKS IT IS LIKE A WEASEL".
* An array of random characters chosen from the set of upper-case letters together with the space, and of the same length as the target string. (Call it the parent).
* A fitness function that computes the 'closeness' of its argument to the target string.
* A mutate function that given a string and a mutation rate returns a copy of the string, with some characters probably mutated.
* While the parent is not yet the target:
:* copy the parent C times, each time allowing some random probability that another character might be substituted using mutate.
:* Assess the fitness of the parent and all the copies to the target and make the most fit string the new parent, discarding the others.
:* repeat until the parent converges, (hopefully), to the target.

;See also:
*   Wikipedia entry:   Weasel algorithm.
*   Wikipedia entry:   Evolutionary algorithm.

Note: to aid comparison, try and ensure the variables and functions mentioned in the task description appear in solutions

A cursory examination of a few of the solutions reveals that the instructions have not been followed rigorously in some solutions. Specifically,
* While the parent is not yet the target:
:* copy the parent C times, each time allowing some random probability that another character might be substituted using mutate.

Note that some of the the solutions given retain characters in the mutated string that are ''correct'' in the target string. However, the instruction above does not state to retain any of the characters while performing the mutation. Although some may believe to do so is implied from the use of "converges"

 (:* repeat until the parent converges, (hopefully), to the target.

Strictly speaking, the new parent should be selected from the new pool of mutations, and then the new parent used to generate the next set of mutations with parent characters getting retained only by ''not'' being mutated. It then becomes possible that the new set of mutations has no member that is fitter than the parent!

As illustration of this error, the code for 8th has the following remark.

 Create a new string based on the TOS, '''changing randomly any characters which
 don't already match the target''':

''NOTE:'' this has been changed, the 8th version is completely random now

Clearly, this algo will be applying the mutation function only to the parent characters that don't match to the target characters!

To ensure that the new parent is never less fit than the prior parent, both the parent and all of the latest mutations are subjected to the fitness test to select the next parent.

Solution:
@target = "METHINKS IT IS LIKE A WEASEL"
Charset = [" ", *"A".."Z"]
COPIES = 100

def random_char; Charset.sample end

def fitness(candidate)
  sum = 0
  candidate.chars.zip(@target.chars) {|x,y| sum += (x[0].ord - y[0].ord).abs}
  100.0 * Math.exp(Float(sum) / -10.0)
end

def mutation_rate(candidate)
  1.0 - Math.exp( -(100.0 - fitness(candidate)) / 400.0)
end

def mutate(parent, rate)
  parent.each_char.collect {|ch| rand <= rate ? random_char : ch}.join
end

def log(iteration, rate, parent)
  puts "%4d %.2f %5.1f %s" % [iteration, rate, fitness(parent), parent]
end

iteration = 0
parent = Array.new(@target.length) {random_char}.join
prev = ""

while parent != @target
  iteration += 1
  rate = mutation_rate(parent)
  if prev != parent
    log(iteration, rate, parent)
    prev = parent
  end
  copies = [parent] + Array.new(COPIES) {mutate(parent, rate)}
  parent = copies.max_by {|c| fitness(c)}
end
log(iteration, rate, parent)


Executable library

The general idea behind an executable library is to create a library
that when used as a library does one thing;
but has the ability to be run directly via command line.
Thus the API comes with a CLI in the very same source code file.

'''Task detail'''

* Create a library/module/dll/shared object/... for a programming language that contains a function/method called hailstone that is a function taking a positive integer and returns the [[Hailstone sequence]] for that number.

* The library, when executed directly should satisfy the remaining requirements of the [[Hailstone sequence]] task:
:: 2.  Use the routine to show that the hailstone sequence for the number 27 has 112 elements starting with 27, 82, 41, 124 and ending with 8, 4, 2, 1
:: 3.  Show the number less than 100,000 which has the longest hailstone sequence together with that sequence's length.

* Create a second executable to calculate the following:
** Use the library's hailstone function, in the standard manner, (or document how this use deviates from standard use of a library), together with extra code in this executable, to find the hailstone length returned most often for 1 <= n < 100,000.

* Explain any extra setup/run steps needed to complete the task.

'''Notes:'''
* It is assumed that for a language that overwhelmingly ships in a compiled form, such as C, the library must also be an executable and the compiled user of that library is to do so without changing the compiled library. I.e. the compile tool-chain is assumed ''not'' to be present in the runtime environment.
* Interpreters are present in the runtime environment.

Solution:
An executable library checks ''__FILE__ == $0''. Here, ''__FILE__'' is the path
of the current source file, and ''$0'' is the path of the current executable.
If ''__FILE__ == $0'', then the current source file is the executable,
else the current source file is a library for some other executable.

* ''__FILE__ == $0'' also works with older versions of Ruby, but this Hailstone example calls new methods in Ruby 1.8.7.

This is ''hailstone.rb'', a modification of [[Hailstone sequence#Ruby]] as an executable library.


Executable library

Solution:
# hailstone.rb
module Hailstone
  module_function
  def hailstone n
    seq = [n]
    until n == 1
      n = (n.even?) ? (n / 2) : (3 * n + 1)
      seq << n
    end
    seq
  end
end

if __FILE__ == $0
  include Hailstone

  # for n = 27, show sequence length and first and last 4 elements
  hs27 = hailstone 27
  p [hs27.length, hs27[0..3], hs27[-4..-1]]

  # find the longest sequence among n less than 100,000
  n, len = (1 ... 100_000) .collect {|n|
    [n, hailstone(n).length]} .max_by {|n, len| len}
  puts "#{n} has a hailstone sequence length of #{len}"
  puts "the largest number in that sequence is #{hailstone(n).max}"
end


Exponentiation order

This task will demonstrate the order of exponentiation   ('''xy''')    when there are multiple exponents.

(Many programming languages,   especially those with extended-precision integer arithmetic,   usually support one of  **, ^, |  or some such for exponentiation.)

;Task requirements
Show the result of a language's evaluation of multiple exponentiation (either as an integer or floating point).

If your language's exponentiation operator is not one of the usual ones, please comment on how to recognize it.

Using whatever operator or syntax your language supports (if any), show the results in three lines (with identification):

::::*   5**3**2
::::*   (5**3)**2
::::*   5**(3**2)

If there are other methods (or formats) of multiple exponentiations, show them as well.

;See also:
* MathWorld entry:   exponentiation

;Related tasks:
*   exponentiation operator
*   arbitrary-precision integers (included)
*   [[Exponentiation with infix operators in (or operating on) the base]]

Solution:
ar = ["5**3**2", "(5**3)**2", "5**(3**2)", "[5,3,2].inject(:**)"]
ar.each{|exp| puts "#{exp}:\t#{eval exp}"}


Exponentiation with infix operators in (or operating on) the base

(Many programming languages,   especially those with extended-precision integer arithmetic,   usually
support one of  **, ^, |  or some such for exponentiation.)

Some languages treat/honor infix operators when performing exponentiation   (raising
numbers to some power by the language's exponentiation operator,   if the computer
programming language has one).

Other programming languages may make use of the   '''POW'''   or some other BIF
  ('''B'''uilt-'''I'''n '''F'''function),   or some other library service.

If your language's exponentiation operator is not one of the usual ones, please comment on how to recognize it.

This task will deal with the case where there is some form of an   ''infix operator''   operating
in   (or operating on)   the base.

;Example:
A negative five raised to the 3rd power could be specified as:
    -5  ** 3          or as
   -(5) ** 3          or as
   (-5) ** 3          or as something else

(Not all computer programming languages have an exponential operator and/or support these syntax expression(s).

;Task:
:*   compute and display exponentiation with a possible infix operator, whether specified and/or implied/inferred.
:*   Raise the following numbers   (integer or real):
:::*   -5     and
:::*   +5
:*   to the following powers:
:::*   2nd     and
:::*   3rd
:*   using the following expressions   (if applicable in your language):
:::*   -x**p
:::*   -(x)**p
:::*   (-x)**p
:::*   -(x**p)
:*   Show here (on this page) the four (or more) types of symbolic expressions for each number and power.

Try to present the results in the same format/manner as the other programming entries to make any differences apparent.

The variables may be of any type(s) that is/are applicable in your language.

;Related tasks:
*   [[Exponentiation order]]
*   [[Exponentiation operator]]
*   [[Arbitrary-precision integers (included)]]
*   [[Parsing/RPN to infix conversion]]
*   [[Operator precedence]]

;References:
* Wikipedia: Order of operations in Programming languages

Solution:
nums = [-5, 5]
pows = [2, 3]
nums.product(pows) do |x, p|
  puts "x = #{x} p = #{p}\t-x**p #{-x**p}\t-(x)**p  #{-(x)**p}\t(-x)**p #{ (-x)**p}\t-(x**p)  #{-(x**p)}"
end


Extend your language

{{Control Structures}}Some programming languages allow you to extend the language. While this can be done to a certain degree in most languages (e.g. by using macros), other languages go much further. Most notably in the Forth and Lisp families, programming per se is done by extending the language without any formal distinction between built-in and user-defined elements.

If your language supports it, show how to introduce a new flow control mechanism. A practical and useful example is a four-way branch:

Occasionally, code must be written that depends on ''two'' conditions, resulting in up to four branches (depending on whether both, only the first, only the second, or none of the conditions are "true"). In a C-like language this could look like the following:

   if (condition1isTrue) {
      if (condition2isTrue)
         bothConditionsAreTrue();
      else
         firstConditionIsTrue();
   }
   else if (condition2isTrue)
      secondConditionIsTrue();
   else
      noConditionIsTrue();

Besides being rather cluttered, the statement(s) for 'condition2isTrue' must be written down twice. If 'condition2isTrue' were a lengthy and involved expression, it would be quite unreadable, and the code generated by the compiler might be unnecessarily large.

This can be improved by introducing a new keyword '''if2'''. It is similar to '''if''', but takes two conditional statements instead of one, and up to three 'else' statements. One proposal (in pseudo-C syntax) might be:

   if2 (condition1isTrue) (condition2isTrue)
      bothConditionsAreTrue();
   else1
      firstConditionIsTrue();
   else2
      secondConditionIsTrue();
   else
      noConditionIsTrue();

Pick the syntax which suits your language. The keywords 'else1' and 'else2' are just examples. The new conditional expression should look, nest and behave analogously to the language's built-in 'if' statement.

Solution:
# Define a class which always returns itself for everything
class HopelesslyEgocentric
  def method_missing(what, *args) self end
end

def if2(cond1, cond2)
  if cond1 and cond2
    yield
    HopelesslyEgocentric.new
  elsif cond1
    Class.new(HopelesslyEgocentric) do
      def else1; yield; HopelesslyEgocentric.new end
    end.new
  elsif cond2
    Class.new(HopelesslyEgocentric) do
      def else2; yield; HopelesslyEgocentric.new end
    end.new
  else
    Class.new(HopelesslyEgocentric) do
      def neither; yield end
    end.new
  end
end


Extreme floating point values

The IEEE floating point specification defines certain 'extreme' floating point values such as minus zero, -0.0, a value distinct from plus zero; not a number, NaN; and plus and minus infinity.

The task is to use expressions involving other 'normal' floating point values in your language to calculate these, (and maybe other), extreme floating point values in your language and assign them to variables.

Print the values of these variables if possible; and show some arithmetic with these values and variables.

If your language can directly enter these extreme floating point values then show it.

;See also:
*   What Every Computer Scientist Should Know About Floating-Point Arithmetic

;Related tasks:
*   [[Infinity]]
*   [[Detect division by zero]]
*   [[Literals/Floating point]]

Solution:
inf = 1.0 / 0.0    # or Float::INFINITY
nan = 0.0 / 0.0               # or Float::NAN

expression = [
  "1.0 / 0.0", "-1.0 / 0.0", "0.0 / 0.0", "- 0.0",
  "inf + 1", "5 - inf", "inf * 5", "inf / 5", "inf * 0",
  "1.0 / inf", "-1.0 / inf", "inf + inf", "inf - inf",
  "inf * inf", "inf / inf", "inf * 0.0", " 0 < inf", "inf == inf",
  "nan + 1", "nan * 5", "nan - nan", "nan * inf", "- nan",
  "nan == nan", "nan > 0", "nan < 0", "nan == 0", "nan <=> 0.0", "0.0 == -0.0",
]

expression.each do |exp|
  puts "%15s => %p" % [exp, eval(exp)]
end


FASTA format

In FASTA.

A FASTA file can contain several strings, each identified by a name marked by a > (greater than) character at the beginning of the line.

;Task:
Write a program that reads a FASTA file such as:

>Rosetta_Example_1
THERECANBENOSPACE
>Rosetta_Example_2
THERECANBESEVERAL
LINESBUTTHEYALLMUST
BECONCATENATED

Solution:
def fasta_format(strings)
  out, text = [], ""
  strings.split("\n").each do |line|
    if line[0] == '>'
      out << text unless text.empty?
      text = line[1..-1] + ": "
    else
      text << line
    end
  end
  out << text unless text.empty?
end

data = <<'EOS'
>Rosetta_Example_1
THERECANBENOSPACE
>Rosetta_Example_2
THERECANBESEVERAL
LINESBUTTHEYALLMUST
BECONCATENATED
EOS

puts fasta_format(data)


Factorial primes

Definition
A factorial.

In other words a non-negative integer '''n''' corresponds to a factorial prime if either '''n'''! - 1 or '''n'''! + 1 is prime.

;Examples
4 corresponds to the factorial prime 4! - 1 = 23.

5 doesn't correspond to a factorial prime because neither 5! - 1 = 119 (7 x 17) nor 5! + 1 = 121 (11 x 11) are prime.

;Task
Find and show here the first 10 factorial primes. As well as the prime itself show the factorial number '''n''' to which it corresponds and whether 1 is to be added or subtracted.

As 0! (by convention) and 1! are both 1, ignore the former and start counting from 1!.

;Stretch
If your language supports arbitrary sized integers, do the same for at least the next 19 factorial primes.

As it can take a long time to demonstrate that a large number (above say 2^64) is definitely prime, you may instead use a function which shows that a number is probably prime to a reasonable degree of certainty. Most 'big integer' libraries have such a function.

If a number has more than 40 digits, do not show the full number. Show instead the first 20 and the last 20 digits and how many digits in total the number has.

;Reference
* OEIS:A088054 - Factorial primes

;Related task
* Sequence of primorial primes

Solution:
require 'openssl'

factorial_primes = Enumerator.new do |y|
  fact = 1
  (1..).each do |i|
    fact *= i
    y << [i, "- 1", fact - 1] if OpenSSL::BN.new(fact - 1).prime?
    y << [i, "+ 1", fact + 1] if OpenSSL::BN.new(fact + 1).prime?
  end
end

factorial_primes.first(30).each do |a|
  s = a.last.to_s
  if s.size > 40 then
    puts "%d! %s = " % a.first(2) + "#{s[0,20]}...#{s[-20,20]}"
  else
    puts "%d! %s = %d" % a
  end
end


Factorions

Definition:
A factorion is a natural number that equals the sum of the factorials of its digits.

;Example:
'''145'''   is a factorion in base '''10''' because:

 1! + 4! + 5!   =   1 + 24 + 120   =   145

It can be shown (see talk page) that no factorion in base '''10''' can exceed   '''1,499,999'''.

;Task:
Write a program in your language to demonstrate, by calculating and printing out the factorions, that:
:*   There are   '''3'''   factorions in base   '''9'''
:*   There are   '''4'''   factorions in base '''10'''
:*   There are   '''5'''   factorions in base '''11'''
:*   There are   '''2'''   factorions in base '''12'''     (up to the same upper bound as for base '''10''')

;See also:
:* '''Wikipedia article'''
:* '''OEIS:A014080 - Factorions in base 10'''
:* '''OEIS:A193163 - Factorions in base n'''

Solution:
def factorion?(n, base)
  n.digits(base).sum{|digit| (1..digit).inject(1, :*)} == n
end

(9..12).each do |base|
  puts "Base #{base} factorions: #{(1..1_500_000).select{|n| factorion?(n, base)}.join(" ")} "
end


Fairshare between two and more

The [[Thue-Morse]] sequence is a sequence of ones and zeros that if two people
take turns in the given order, the first persons turn for every '0' in the
sequence, the second for every '1'; then this is shown to give a fairer, more
equitable sharing of resources. (Football penalty shoot-outs for example, might
not favour the team that goes first as much if the penalty takers take turns
according to the Thue-Morse sequence and took 2^n penalties)

The Thue-Morse sequence of ones-and-zeroes can be generated by:
:''"When counting in binary, the digit sum modulo 2 is the Thue-Morse sequence"''

;Sharing fairly between two or more:
Use this method:
:''When counting base '''b''', the digit sum modulo '''b''' is the Thue-Morse sequence of fairer sharing between '''b''' people.''

;Task
Counting from zero;   using a function/method/routine to express an integer count in base '''b''',
sum the digits modulo '''b''' to produce the next member of the Thue-Morse fairshare series for '''b''' people.

Show the first 25 terms of the fairshare sequence:
:*   For two people:
:*   For three people
:*   For five people
:*   For eleven people

;Related tasks:
:*   [[Non-decimal radices/Convert]]
:*   [[Thue-Morse]]

;See also:
:*   A010060, A053838, A053840: The On-Line Encyclopedia of Integer Sequences(r) (OEIS(r))

Solution:
def turn(base, n)
    sum = 0
    while n != 0 do
        rem = n % base
        n = n / base
        sum = sum + rem
    end
    return sum % base
end

def fairshare(base, count)
    print "Base %2d: " % [base]
    for i in 0 .. count - 1 do
        t = turn(base, i)
        print " %2d" % [t]
    end
    print "\n"
end

def turnCount(base, count)
    cnt = Array.new(base, 0)

    for i in 0 .. count - 1 do
        t = turn(base, i)
        cnt[t] = cnt[t] + 1
    end

    minTurn = base * count
    maxTurn = -1
    portion = 0
    for i in 0 .. base - 1 do
        if cnt[i] > 0 then
            portion = portion + 1
        end
        if cnt[i] < minTurn then
            minTurn = cnt[i]
        end
        if cnt[i] > maxTurn then
            maxTurn = cnt[i]
        end
    end

    print "  With %d people: " % [base]
    if 0 == minTurn then
        print "Only %d have a turn\n" % portion
    elsif minTurn == maxTurn then
        print "%d\n" % [minTurn]
    else
        print "%d or %d\n" % [minTurn, maxTurn]
    end
end

def main
    fairshare(2, 25)
    fairshare(3, 25)
    fairshare(5, 25)
    fairshare(11, 25)

    puts "How many times does each get a turn in 50000 iterations?"
    turnCount(191, 50000)
    turnCount(1377, 50000)
    turnCount(49999, 50000)
    turnCount(50000, 50000)
    turnCount(50001, 50000)
end

main()


Fairshare between two and more

Solution:
def fairshare(base, upto) = (0...upto).map{|n| n.digits(base).sum % base}

upto = 25
[2, 3, 5, 11].each{|b| puts"#{'%2d' % b}: " + " %2d"*upto % fairshare(b, upto)}


Farey sequence

The   Farey sequence   ''' ''F''n'''   of order   '''n'''   is the sequence of completely reduced fractions between   '''0'''   and   '''1'''   which, when in lowest terms, have denominators less than or equal to   '''n''',   arranged in order of increasing size.

The   ''Farey sequence''   is sometimes incorrectly called a   ''Farey series''.

Each Farey sequence:
:::*   starts with the value   '''0'''   (zero),   denoted by the fraction      \frac{0}{1}
:::*   ends with the value   '''1'''   (unity),   denoted by the fraction    \frac{1}{1}.

The Farey sequences of orders   '''1'''   to   '''5'''   are:

:::: {\bf\it{F}}_1 = \frac{0}{1}, \frac{1}{1}
:
:::: {\bf\it{F}}_2 = \frac{0}{1}, \frac{1}{2}, \frac{1}{1}
:
:::: {\bf\it{F}}_3 = \frac{0}{1}, \frac{1}{3}, \frac{1}{2}, \frac{2}{3}, \frac{1}{1}
:
:::: {\bf\it{F}}_4 = \frac{0}{1}, \frac{1}{4}, \frac{1}{3}, \frac{1}{2}, \frac{2}{3}, \frac{3}{4}, \frac{1}{1}
:
:::: {\bf\it{F}}_5 = \frac{0}{1}, \frac{1}{5}, \frac{1}{4}, \frac{1}{3}, \frac{2}{5}, \frac{1}{2}, \frac{3}{5}, \frac{2}{3}, \frac{3}{4}, \frac{4}{5}, \frac{1}{1}

;Task
*   Compute and show the Farey sequence for orders   '''1'''   through   '''11'''   (inclusive).
*   Compute and display the   ''number''   of fractions in the Farey sequence for order   '''100'''   through   '''1,000'''   (inclusive)   by hundreds.
*   Show the fractions as    '''n/d'''    (using the solidus [or slash] to separate the numerator from the denominator).

The length   (the number of fractions)   of a Farey sequence asymptotically approaches:

:::::::::::  3 x n2   /   \pi2

;See also:
*    OEIS sequence           A006842 numerators of Farey series of order 1, 2, ***
*    OEIS sequence           A006843 denominators of Farey series of order 1, 2, ***
*    OEIS sequence           A005728 number of fractions in Farey series of order n
*   MathWorld entry          Farey sequence
*   Wikipedia   entry   Farey sequence

Solution:
def farey(n, length=false)
  if length
    (n*(n+3))/2 - (2..n).sum{|k| farey(n/k, true)}
  else
    (1..n).each_with_object([]){|k,a|(0..k).each{|m|a << Rational(m,k)}}.uniq.sort
  end
end

puts 'Farey sequence for order 1 through 11 (inclusive):'
for n in 1..11
  puts "F(#{n}): " + farey(n).join(", ")
end
puts 'Number of fractions in the Farey sequence:'
for i in (100..1000).step(100)
  puts "F(%4d) =%7d" % [i, farey(i, true)]
end


Fast Fourier transform

Calculate the   FFT   (Fast Fourier Transform)   of an input sequence.

The most general case allows for complex numbers at the input
and results in a sequence of equal length, again of complex numbers.
If you need to restrict yourself to real numbers, the output should
be the magnitude   (i.e.:   sqrt(re2 + im2))   of the complex result.

The classic version is the recursive Cooley-Tukey FFT. Wikipedia has pseudo-code for that.
Further optimizations are possible but not required.

Solution:
def fft(vec)
  return vec if vec.size <= 1
  evens_odds = vec.partition.with_index{|_,i| i.even?}
  evens, odds = evens_odds.map{|even_odd| fft(even_odd)*2}
  evens.zip(odds).map.with_index do |(even, odd),i|
    even + odd * Math::E ** Complex(0, -2 * Math::PI * i / vec.size)
  end
end

fft([1,1,1,1,0,0,0,0]).each{|c| puts "%9.6f %+9.6fi" % c.rect}


Feigenbaum constant calculation

Calculate the Feigenbaum constant.

;See:
:*   Details in the Wikipedia article:   Feigenbaum constant.

Solution:
def main
    maxIt = 13
    maxItJ = 10
    a1 = 1.0
    a2 = 0.0
    d1 = 3.2
    puts " i       d"
    for i in 2 .. maxIt
        a = a1 + (a1 - a2) / d1
        for j in 1 .. maxItJ
            x = 0.0
            y = 0.0
            for k in 1 .. 1 << i
                y = 1.0 - 2.0 * y * x
                x = a - x * x
            end
            a = a - x / y
        end
        d = (a1 - a2) / (a - a1)
        print "%2d    %.8f\n" % [i, d]
        d1 = d
        a2 = a1
        a1 = a
    end
end

main()


Fibonacci n-step number sequences

These number series are an expansion of the ordinary [[Fibonacci sequence]] where:
# For n = 2 we have the Fibonacci sequence; with initial values [1, 1] and F_k^2 = F_{k-1}^2 + F_{k-2}^2
# For n = 3 we have the tribonacci sequence; with initial values [1, 1, 2] and F_k^3 = F_{k-1}^3 + F_{k-2}^3 + F_{k-3}^3
# For n = 4 we have the tetranacci sequence; with initial values [1, 1, 2, 4] and F_k^4 = F_{k-1}^4 + F_{k-2}^4 + F_{k-3}^4 + F_{k-4}^4...
# For general n>2 we have the Fibonacci n-step sequence - F_k^n; with initial values of the first n values of the (n-1)'th Fibonacci n-step sequence F_k^{n-1}; and k'th value of this n'th sequence being F_k^n = \sum_{i=1}^{(n)} {F_{k-i}^{(n)}}

For small values of n, Greek numeric prefixes are sometimes used to individually name each series.

:::: {| style="text-align: left;" border="4" cellpadding="2" cellspacing="2"
|+ Fibonacci n-step sequences
|- style="background-color: rgb(255, 204, 255);"
! n !! Series name !! Values
|-
|  2 ||  fibonacci || 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 ...
|-
|  3 || tribonacci || 1 1 2 4 7 13 24 44 81 149 274 504 927 1705 3136 ...
|-
|  4 || tetranacci || 1 1 2 4 8 15 29 56 108 208 401 773 1490 2872 5536 ...
|-
|  5 || pentanacci || 1 1 2 4 8 16 31 61 120 236 464 912 1793 3525 6930 ...
|-
|  6 ||  hexanacci || 1 1 2 4 8 16 32 63 125 248 492 976 1936 3840 7617 ...
|-
|  7 || heptanacci || 1 1 2 4 8 16 32 64 127 253 504 1004 2000 3984 7936 ...
|-
|  8 ||  octonacci || 1 1 2 4 8 16 32 64 128 255 509 1016 2028 4048 8080 ...
|-
|  9 ||  nonanacci || 1 1 2 4 8 16 32 64 128 256 511 1021 2040 4076 8144 ...
|-
| 10 ||  decanacci || 1 1 2 4 8 16 32 64 128 256 512 1023 2045 4088 8172 ...
|}

Allied sequences can be generated where the initial values are changed:
: '''The Lucas series''' sums the two preceding values like the fibonacci series for n=2 but uses [2, 1] as its initial values.

;Task:
# Write a function to generate Fibonacci n-step number sequences given its initial values and assuming the number of initial values determines how many previous values are summed to make the next number of the series.
# Use this to print and show here at least the first ten members of the Fibo/tribo/tetra-nacci and Lucas sequences.

;Related tasks:
*   [[Fibonacci sequence]]
*   Wolfram Mathworld
*   [[Hofstadter Q sequence]]
*   [[Leonardo numbers]]

;Also see:
*   Lucas Numbers - Numberphile (Video)
*   Tribonacci Numbers (and the Rauzy Fractal) - Numberphile (Video)
*   Wikipedia, Lucas number
*   MathWorld, Fibonacci Number
*   Some identities for r-Fibonacci numbers
*   OEIS Fibonacci numbers
*   OEIS Lucas numbers

Solution:
def anynacci(start_sequence, count)
  n      = start_sequence.length    # Get the n-step for the type of fibonacci sequence
  result = start_sequence.dup       # Create a new result array with the values copied from the array that was passed by reference
  (count-n).times do                # Loop for the remaining results up to count
    result << result.last(n).sum    # Get the last n element from result and append its total to Array
  end
  result
end

naccis = { lucas:      [2,1],
           fibonacci:  [1,1],
           tribonacci: [1,1,2],
           tetranacci: [1,1,2,4],
           pentanacci: [1,1,2,4,8],
           hexanacci:  [1,1,2,4,8,16],
           heptanacci: [1,1,2,4,8,16,32],
           octonacci:  [1,1,2,4,8,16,32,64],
           nonanacci:  [1,1,2,4,8,16,32,64,128],
           decanacci:  [1,1,2,4,8,16,32,64,128,256] }

naccis.each {|name, seq| puts "%12s : %p" % [name, anynacci(seq, 15)]}


Fibonacci word

The   Fibonacci Word   may be created in a manner analogous to the   Fibonacci Sequence    as described here:

     Define   F_Word1   as   '''1'''
     Define   F_Word2   as   '''0'''
     Form     F_Word3   as   F_Word2     concatenated with   F_Word1    i.e.:   '''01'''
     Form     F_Wordn   as   F_Wordn-1   concatenated with   F_wordn-2

;Task:
Perform the above steps for     n = 37.

You may display the first few but not the larger values of   n.
{Doing so will get the task's author into trouble with them what be (again!).}

Instead, create a table for   F_Words   '''1'''   to   '''37'''   which shows:
::*   The number of characters in the word
::*   The word's [[Entropy]]

;Related tasks:
*   Fibonacci word/fractal
*   [[Entropy]]
*   [[Entropy/Narcissist]]

Solution:
#encoding: ASCII-8BIT

def entropy(s)
  counts = Hash.new(0.0)
  s.each_char { |c| counts[c] += 1 }
  leng = s.length

  counts.values.reduce(0) do |entropy, count|
    freq = count / leng
    entropy - freq * Math.log2(freq)
  end
end

n_max = 37
words = ['1', '0']

for n in words.length ... n_max
  words << words[-1] + words[-2]
end

puts '%3s %9s %15s  %s' % %w[N Length Entropy Fibword]
words.each.with_index(1) do |word, i|
  puts '%3i %9i %15.12f  %s' % [i, word.length, entropy(word), word.length<60 ? word : '<too long>']
end


File extension is in extensions list

Checking if a file is in a certain category of file formats with known extensions (e.g. archive files, or image files) is a common problem in practice, and may be approached differently from extracting and outputting an arbitrary extension ''(see e.g. FileNameExtensionFilter in Java)''.

It also requires less assumptions about the format of an extension, because the calling code can decide what extensions are valid.

For these reasons, this task exists in addition to the [[Extract file extension]] task.

;Related tasks:
* [[Extract file extension]]
* [[String matching]]

Solution:
def is_ext(filename, extensions)
  if filename.respond_to?(:each)
    filename.each do |fn|
      is_ext(fn, extensions)
    end
  else
    fndc = filename.downcase
    extensions.each do |ext|
      bool = fndc.end_with?(?. + ext.downcase)
      puts "%20s : %s" % [filename, bool] if bool
    end
  end
end


Find Chess960 starting position identifier

Starting Position Identifier number ("SP-ID"), and generate the corresponding position.

;Task:
This task is to go the other way: given a starting array of pieces (provided in any form that suits your implementation, whether string or list or array, of letters or Unicode chess symbols or enum values, etc.), derive its unique SP-ID. For example, given the starting array '''QNRBBNKR''' (or '''''' or ''''''), which we assume is given as seen from White's side of the board from left to right, your (sub)program should return 105; given the starting lineup of standard chess, it should return 518.

You may assume the input is a valid Chess960 position; detecting invalid input (including illegal characters or starting arrays with the bishops on the same color square or the king not between the two rooks) is optional.

;Algorithm:

The derivation is the inverse of the algorithm given at Wikipedia, and goes like this (we'll use the standard chess setup as an example).

1. Ignoring the Queen and Bishops, find the positions of the Knights within the remaining five spaces (in the standard array they're in the second and fourth positions), and then find the index number of that combination. There's a table at the above Wikipedia article, but it's just the possible positions sorted left to right and numbered 0 to 9: 0='''NN---''', 1='''N-N--''', 2='''N--N-''', 3='''N---N''', 4='''-NN--''', etc; our pair is combination number 5. Call this number N. '''N=5'''

2. Still ignoring the Bishops, find the position of the Queen in the remaining 6 spaces; number them 0..5 from left to right and call the index of the Queen's position Q. In our example, '''Q=2'''.

3. Finally, find the positions of the two bishops within their respective sets of four like-colored squares. It's important to note here that the board in chess is placed such that the leftmost position on the home row is on a dark square and the rightmost a light. So if we number the squares of each color 0..3 from left to right, the dark bishop in the standard position is on square 1 ('''D=1'''), and the light bishop is on square 2 ('''L=2''').

4. Then the position number is given by '''4(4(6N + Q)+D)+L''', which reduces to '''96N + 16Q + 4D + L'''. In our example, that's 96x5 + 16x2 + 4x1 + 2 = 480 + 32 + 4 + 2 = 518.

Note that an earlier iteration of this page contained an incorrect description of the algorithm which would give the same SP-ID for both of the following two positions.

    RQNBBKRN = 601
    RNQBBKRN = 617

Solution:
CHESS_PIECES = %w<♖♘♗♕♔ ♜♞♝♛♚>
def chess960_to_spid(pos)
  start_str = pos.tr(CHESS_PIECES.join, "RNBQKRNBQK")
  #1 knights score
  s = start_str.delete("QB")
  n = [0,1,2,3,4].combination(2).to_a.index( [s.index("N"), s.rindex("N")] )
  #2 queen score
  q = start_str.delete("B").index("Q")
  #3 bishops
  bs = start_str.index("B"), start_str.rindex("B")
  d = bs.detect(&:even?).div(2)
  l = bs.detect(&:odd? ).div(2)

  96*n + 16*q + 4*d + l
end

%w<QNRBBNKR RNBQKBNR RQNBBKRN RNQBBKRN>.each_with_index do |array, i|
  pieces = array.tr("RNBQK", CHESS_PIECES[i%2])
  puts "#{pieces} (#{array}):  #{chess960_to_spid array}"
end


Find duplicate files

In a large directory structure it is easy to inadvertently leave unnecessary copies of files around, which can use considerable disk space and create confusion.

;Task:
Create a program which, given a minimum size and a folder/directory, will find all files of at least ''size'' bytes with duplicate contents under the directory and output or show the sets of duplicate files in order of decreasing size.

The program may be command-line or graphical, and duplicate content may be determined by direct comparison or by calculating a hash of the data.

Specify which filesystems or operating systems your program works with if it has any filesystem- or OS-specific requirements.

Identify hard links (filenames referencing the same content) in the output if applicable for the filesystem.

For extra points, detect when whole directory sub-trees are identical, or optionally remove or link identical files.

Solution:
require 'digest/md5'

def find_duplicate_files(dir)
  puts "\nDirectory : #{dir}"
  Dir.chdir(dir) do
    file_size = Dir.foreach('.').select{|f| FileTest.file?(f)}.group_by{|f| File.size(f)}
    file_size.each do |size, files|
      next if files.size==1
      files.group_by{|f| Digest::MD5.file(f).to_s}.each do |md5,fs|
        next if fs.size==1
        puts "  --------------------------------------------"
        fs.each{|file| puts "  #{File.mtime(file)}  #{size}  #{file}"}
      end
    end
  end
end

find_duplicate_files("/Windows/System32")


Find if a point is within a triangle

Find if a point is within a triangle.

;Task:

::*   Assume points are on a plane defined by (x, y) real number coordinates.

::*   Given a point P(x, y) and a triangle formed by points A, B, and C, determine if P is within triangle ABC.

::*   You may use any algorithm.

::*   Bonus: explain why the algorithm you chose works.

;Related tasks:
*   [[Determine_if_two_triangles_overlap]]

;Also see:
:* Discussion of several methods. [[http://totologic.blogspot.com/2014/01/accurate-point-in-triangle-test.html]]
:* Determine if a point is in a polygon [[https://en.wikipedia.org/wiki/Point_in_polygon]]
:* Triangle based coordinate systems [[https://en.wikipedia.org/wiki/Barycentric_coordinate_system]]
:* Wolfram entry [[https://mathworld.wolfram.com/TriangleInterior.html]]

Solution:
EPS = 0.001
EPS_SQUARE = EPS * EPS

def side(x1, y1, x2, y2, x, y)
    return (y2 - y1) * (x - x1) + (-x2 + x1) * (y - y1)
end

def naivePointInTriangle(x1, y1, x2, y2, x3, y3, x, y)
    checkSide1 = side(x1, y1, x2, y2, x, y) >= 0
    checkSide2 = side(x2, y2, x3, y3, x, y) >= 0
    checkSide3 = side(x3, y3, x1, y1, x, y) >= 0
    return checkSide1 && checkSide2 && checkSide3
end

def pointInTriangleBoundingBox(x1, y1, x2, y2, x3, y3, x, y)
    xMin = [x1, x2, x3].min - EPS
    xMax = [x1, x2, x3].max + EPS
    yMin = [y1, y2, y3].min - EPS
    yMax = [y1, y2, y3].max + EPS
    return !(x < xMin || xMax < x || y < yMin || yMax < y)
end

def distanceSquarePointToSegment(x1, y1, x2, y2, x, y)
    p1_p2_squareLength = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)
    dotProduct = ((x - x1) * (x2 - x1) + (y - y1) * (y2 - y1)) / p1_p2_squareLength
    if dotProduct < 0 then
        return (x - x1) * (x - x1) + (y - y1) * (y - y1)
    end
    if dotProduct <= 1 then
        p_p1_squareLength = (x1 - x) * (x1 - x) + (y1 - y) * (y1 - y)
        return p_p1_squareLength - dotProduct * dotProduct * p1_p2_squareLength
    end
    return (x - x2) * (x - x2) + (y - y2) * (y - y2)
end

def accuratePointInTriangle(x1, y1, x2, y2, x3, y3, x, y)
    if !pointInTriangleBoundingBox(x1, y1, x2, y2, x3, y3, x, y) then
        return false
    end
    if naivePointInTriangle(x1, y1, x2, y2, x3, y3, x, y) then
        return true
    end
    if distanceSquarePointToSegment(x1, y1, x2, y2, x, y) <= EPS_SQUARE then
        return true
    end
    if distanceSquarePointToSegment(x2, y2, x3, y3, x, y) <= EPS_SQUARE then
        return true
    end
    if distanceSquarePointToSegment(x3, y3, x1, y1, x, y) <= EPS_SQUARE then
        return true
    end
    return false
end

def main
    pts = [[0, 0], [0, 1], [3, 1]]
    tri = [[1.5, 2.4], [5.1, -3.1], [-3.8, 1.2]]
    print "Triangle is ", tri, "\n"
    x1, y1 = tri[0][0], tri[0][1]
    x2, y2 = tri[1][0], tri[1][1]
    x3, y3 = tri[2][0], tri[2][1]
    for pt in pts
        x, y = pt[0], pt[1]
        within = accuratePointInTriangle(x1, y1, x2, y2, x3, y3, x, y)
        print "Point ", pt, " is within triangle? ", within, "\n"
    end
    print "\n"

    tri = [[0.1, 1.0 / 9.0], [12.5, 100.0 / 3.0], [25.0, 100.0 / 9.0]]
    print "Triangle is ", tri, "\n"
    x1, y1 = tri[0][0], tri[0][1]
    x2, y2 = tri[1][0], tri[1][1]
    x3, y3 = tri[2][0], tri[2][1]
    x = x1 + (3.0 / 7.0) * (x2 - x1)
    y = y1 + (3.0 / 7.0) * (y2 - y1)
    pt = [x, y]
    within = accuratePointInTriangle(x1, y1, x2, y2, x3, y3, x, y)
    print "Point ", pt, " is within triangle? ", within, "\n"
    print "\n"

    tri = [[0.1, 1.0 / 9.0], [12.5, 100.0 / 3.0], [-12.5, 100.0 / 6.0]]
    print "Triangle is ", tri, "\n"
    x3, y3 = tri[2][0], tri[2][1]
    within = accuratePointInTriangle(x1, y1, x2, y2, x3, y3, x, y)
    print "Point ", pt, " is within triangle? ", within, "\n"
end

main()


Find palindromic numbers in both binary and ternary bases

*   Find and show (in decimal) the first six numbers (non-negative integers) that are   palindromes   in   ''both'':
:::*   base 2
:::*   base 3
*   Display   '''0'''   (zero) as the first number found, even though some other definitions ignore it.
*   Optionally, show the decimal number found in its binary and ternary form.
*   Show all output here.

It's permissible to assume the first two numbers and simply list them.

;See also
*   Sequence A60792,   numbers that are palindromic in bases 2 and 3 on ''The On-Line Encyclopedia of Integer Sequences''.

Solution:
pal23 = Enumerator.new do |y|
  y << 0
  y << 1
  for i in 1 .. 1.0/0.0                 # 1.step do |i|  (Ruby 2.1+)
    n3 = i.to_s(3)
    n = (n3 + "1" + n3.reverse).to_i(3)
    n2 = n.to_s(2)
    y << n  if n2.size.odd? and n2 == n2.reverse
  end
end

puts "         decimal          ternary                          binary"
6.times do |i|
  n = pal23.next
  puts "%2d: %12d %s %s" % [i, n, n.to_s(3).center(25), n.to_s(2).center(39)]
end


Find the intersection of a line with a plane

Finding the intersection of an infinite ray with a plane in 3D is an important topic in collision detection.

;Task:
Find the point of intersection for the infinite ray with direction   (0, -1, -1)   passing through position   (0, 0, 10)   with the infinite plane with a normal vector of   (0, 0, 1)   and which passes through [0, 0, 5].

Solution:
require "matrix"

def intersectPoint(rayVector, rayPoint, planeNormal, planePoint)
    diff = rayPoint - planePoint
    prod1 = diff.dot planeNormal
    prod2 = rayVector.dot planeNormal
    prod3 = prod1 / prod2
    return rayPoint - rayVector * prod3
end

def main
    rv = Vector[0.0, -1.0, -1.0]
    rp = Vector[0.0, 0.0, 10.0]
    pn = Vector[0.0, 0.0, 1.0]
    pp = Vector[0.0, 0.0, 5.0]
    ip = intersectPoint(rv, rp, pn, pp)
    puts "The ray intersects the plane at %s" % [ip]
end

main()


Find the intersection of two lines

Finding the intersection of two lines that are in the same plane is an important topic in collision detection.[http://mathworld.wolfram.com/Line-LineIntersection.html]

;Task:
Find the point of intersection of two lines in 2D.

The 1st     line passes though    (4,0)    and    (6,10) .
The 2nd line passes though    (0,3)    and    (10,7) .

Solution:
Point = Struct.new(:x, :y)

class Line
  attr_reader :a, :b

  def initialize(point1, point2)
    @a = (point1.y - point2.y).fdiv(point1.x - point2.x)
    @b = point1.y - @a*point1.x
  end

  def intersect(other)
    return nil if @a == other.a
    x = (other.b - @b).fdiv(@a - other.a)
    y = @a*x + @b
    Point.new(x,y)
  end

  def to_s
    "y = #{@a}x #{@b.positive? ? '+' : '-'} #{@b.abs}"
  end

end

l1 = Line.new(Point.new(4, 0), Point.new(6, 10))
l2 = Line.new(Point.new(0, 3), Point.new(10, 7))

puts "Line #{l1} intersects line #{l2} at #{l1.intersect(l2)}."


Find the last Sunday of each month

Write a program or a script that returns the last Sundays of each month of a given year. The year may be given through any simple input method in your language (command line, std in, etc).

Example of an expected output:

./last_sundays 2013
2013-01-27
2013-02-24
2013-03-31
2013-04-28
2013-05-26
2013-06-30
2013-07-28
2013-08-25
2013-09-29
2013-10-27
2013-11-24
2013-12-29

;Related tasks
* [[Day of the week]]
* [[Five weekends]]
* [[Last Friday of each month]]

Solution:
require 'date'

def last_sundays_of_year(year = Date.today.year)
  (1..12).map do |month|
    d = Date.new(year, month, -1) # -1 means "last".
    d - d.wday
  end
end

puts last_sundays_of_year(2013)


Find the missing permutation

ABCD
                    CABD
                    ACDB
                    DACB
                    BCDA
                    ACBD
                    ADCB
                    CDAB
                    DABC
                    BCAD
                    CADB
                    CDBA
                    CBAD
                    ABDC
                    ADBC
                    BDCA
                    DCBA
                    BACD
                    BADC
                    BDAC
                    CBDA
                    DBCA
                    DCAB

Listed above are   all-but-one   of the permutations of the symbols   '''A''',   '''B''',   '''C''',   and   '''D''',   ''except''   for one permutation that's   ''not''   listed.

;Task:
Find that missing permutation.

;Methods:
* Obvious method:
         enumerate all permutations of   '''A''',  '''B''',  '''C''',  and  '''D''',
         and then look for the missing permutation.

* alternate method:
         Hint:  if all permutations were shown above,  how many
         times would  '''A'''  appear in each position?
         What is the  ''parity''  of this number?

* another alternate method:
         Hint:  if you add up the letter values of each column,
         does a missing letter   '''A''',  '''B''',  '''C''',  and  '''D'''   from each
         column cause the total value for each column to be unique?

;Related task:
*   [[Permutations]])

Solution:
given = %w{
  ABCD CABD ACDB DACB BCDA ACBD ADCB CDAB DABC BCAD CADB CDBA
  CBAD ABDC ADBC BDCA DCBA BACD BADC BDAC CBDA DBCA DCAB
}

all = given[0].chars.permutation.collect(&:join)

puts "missing: #{all - given}"


First-class functions/Use numbers analogously

In [[First-class functions]], a language is showing how its manipulation of functions is similar to its manipulation of other types.

This tasks aim is to compare and contrast a language's implementation of first class functions, with its normal handling of numbers.

Write a program to create an ordered collection of a mixture of literally typed and expressions producing a real number, together with another ordered collection of their multiplicative inverses. Try and use the following pseudo-code to generate the numbers for the ordered collections:
   x  = 2.0
   xi = 0.5
   y  = 4.0
   yi = 0.25
   z  = x + y
   zi = 1.0 / ( x + y )

Create a function ''multiplier'', that given two numbers as arguments returns a function that when called with one argument, returns the result of multiplying the two arguments to the call to multiplier that created it and the argument in the call:
  new_function = multiplier(n1,n2)
  # where new_function(m) returns the result of n1 * n2 * m

Applying the multiplier of a number and its inverse from the two ordered collections of numbers in pairs, show that the result in each case is one.
'''Compare and contrast the resultant program with the corresponding entry in [[First-class functions]].''' They should be close.

To paraphrase the task description: Do what was done before, but with numbers rather than functions

Solution:
multiplier = proc {|n1, n2| proc {|m| n1 * n2 * m}}
numlist = [x=2, y=4, x+y]
invlist = [0.5, 0.25, 1.0/(x+y)]
p numlist.zip(invlist).map {|n, invn| multiplier[invn, n][0.5]}
# => [0.5, 0.5, 0.5]


First perfect square in base n with n unique digits

Find the first perfect square in a given base '''N''' that has at least '''N''' digits and
exactly '''N''' ''significant unique'' digits when expressed in base '''N'''.

E.G. In base '''10''', the first perfect square with at least '''10''' unique digits is '''1026753849''' ('''320432''').

You may use analytical methods to reduce the search space, but the code must do a search. Do not use magic numbers or just feed the code the answer to verify it is correct.

;Task

* Find and display here, on this page, the first perfect square in base '''N''', with '''N''' significant unique digits when expressed in base '''N''', for each of base '''2''' through '''12'''. Display each number in the base '''N''' for which it was calculated.

* (optional) Do the same for bases '''13''' through '''16'''.

* (stretch goal) Continue on for bases '''17''' - '''??''' (Big Integer math)

;See also:

;* OEIS A260182: smallest square that is pandigital in base n.

;Related task

;* [[Casting out nines]]

Solution:
DIGITS = "1023456789abcdefghijklmnopqrstuvwxyz"

2.upto(16) do |n|
  start = Integer.sqrt( DIGITS[0,n].to_i(n) )
  res = start.step.detect{|i| (i*i).digits(n).uniq.size == n }
  puts "Base %2d:%10s² = %-14s" % [n, res.to_s(n), (res*res).to_s(n)]
end


First power of 2 that has leading decimal digits of 12

Solution:
def p(l, n)
    test = 0
    logv = Math.log(2.0) / Math.log(10.0)
    factor = 1
    loopv = l
    while loopv > 10 do
        factor = factor * 10
        loopv = loopv / 10
    end
    while n > 0 do
        test = test + 1
        val = (factor * (10.0 ** ((test * logv).modulo(1.0)))).floor
        if val == l then
            n = n - 1
        end
    end
    return test
end

def runTest(l, n)
    print "P(%d, %d) = %d\n" % [l, n, p(l, n)]
end

runTest(12, 1)
runTest(12, 2)
runTest(123, 45)
runTest(123, 12345)
runTest(123, 678910)


Fivenum

Many big data or scientific programs use boxplots to show distributions of data.   In addition, sometimes saving large arrays for boxplots can be impractical and use extreme amounts of RAM.   It can be useful to save large arrays as arrays with five numbers to save memory.

For example, the   '''R'''   programming language implements Tukey's five-number summary as the '''fivenum''' function.

;Task:
Given an array of numbers, compute the five-number summary.

;Note:
While these five numbers can be used to draw a boxplot,   statistical packages will typically need extra data.

Moreover, while there is a consensus about the "box" of the boxplot,   there are variations among statistical packages for the whiskers.

Solution:
def fivenum(array)
  sorted_arr = array.sort
  n = array.size
  n4 = (((n + 3).to_f / 2.to_f) / 2.to_f).floor
  d = Array.[](1, n4, ((n.to_f + 1) / 2).to_i, n + 1 - n4, n)
  sum_array = []
  (0..4).each do |e| # each loops have local scope, for loops don't
    index_floor = (d[e] - 1).floor
    index_ceil  = (d[e] - 1).ceil
    sum_array.push(0.5 * (sorted_arr[index_floor] + sorted_arr[index_ceil]))
  end
  sum_array
end

test_array = [15, 6, 42, 41, 7, 36, 49, 40, 39, 47, 43]
tukey_array = fivenum(test_array)
p tukey_array
test_array = [36, 40, 7, 39, 41, 15]
tukey_array = fivenum(test_array)
p tukey_array
test_array = [0.14082834, 0.09748790, 1.73131507, 0.87636009, -1.95059594,
              0.73438555, -0.03035726, 1.46675970, -0.74621349, -0.72588772,
              0.63905160,  0.61501527, -0.98983780, -1.00447874, -0.62759469,
              0.66206163,  1.04312009, -0.10305385, 0.75775634,  0.32566578]
tukey_array = fivenum(test_array)
p tukey_array


Fixed length records

Fixed length read/write

Before terminals, computers commonly used punch card readers or paper tape input.

A common format before these devices were superseded by terminal technology was based on the Hollerith code, Hollerith code.

These input devices handled 80 columns per card and had a limited character set, encoded by punching holes in one or more rows of the card for each column.

These devices assumed/demanded a fixed line width of 80 characters, newlines were not required (and could not even be encoded in some systems).

;Task:
Write a program to read 80 column fixed length records (no newline terminators (but newline characters allowed in the data)) and then write out the reverse of each line as fixed length 80 column records.

Samples here use printable characters, but that is not a given with fixed length data.  Filenames used are sample.txt, infile.dat, outfile.dat.

'''Note:''' There are no newlines, inputs and outputs are fixed at 80 columns, no more, no less, space padded.  Fixed length data is 8 bit complete.  NUL bytes of zero are allowed.

These fixed length formats are still in wide use on mainframes, with JCL and with COBOL (which commonly use EBCDIC encoding and not ASCII).  Most of the large players in day to day financial transactions know all about fixed length records and the expression ''logical record length''.

;Sample data:
To create the sample input file, use an editor that supports fixed length records or use a conversion utility.  For instance, most GNU/Linux versions of '''dd''' support blocking and unblocking records with a conversion byte size.

Line 1...1.........2.........3.........4.........5.........6.........7.........8
Line 2
Line 3
Line 4

Line 6
Line 7
     Indented line 8............................................................
Line 9                                                                 RT MARGIN
prompt$ dd if=sample.txt of=infile.dat cbs=80 conv=block will create a fixed length record file of 80 bytes given newline delimited text input.

prompt$ dd if=infile.dat cbs=80 conv=unblock will display a file with 80 byte logical record lengths to standard out as standard text with newlines.

;Bonus round:
Forth systems often include BLOCK words.  A block is 1024 bytes.  Source code is stored as 16 lines of 64 characters each (again, no newline character or sequence to mark the end of a line).

Write a program to convert a block file to text (using newlines). Trailing spaces should be excluded from the output.

Also demonstrate how to convert from a normal text file to block form. All lines either truncated or padded to 64 characters with no newline terminators. The last block filled to be exactly 1024 characters by adding blanks if needed. Assume a full range of 8 bit byte values for each character.

The COBOL example uses forth.txt and forth.blk filenames.

Solution:
open("outfile.dat", "w") do |out_f|
  open("infile.dat") do |in_f|
     while record = in_f.read(80)
       out_f << record.reverse
     end
  end
end  # both files automatically closed


Flatten a list

Write a function to flatten the nesting in an arbitrary list of values.

Your program should work on the equivalent of this list:
   [[1], 2, [[3, 4], 5], [[[]]], [[[6]]], 7, 8, []]
Where the correct result would be the list:
    [1, 2, 3, 4, 5, 6, 7, 8]

;Related task:
*   [[Tree traversal]]

Solution:
p flatten_once = [[1], 2, [[3,4], 5], [[[]]], [[[6]]], 7, 8, []].flatten(1)
# => [1, 2, [3, 4], 5, [[]], [[6]], 7, 8]