Flipping bits game

The game:
Given an   '''NxN'''   square array of zeroes or ones in an initial configuration,   and a target configuration of zeroes and ones.

The game is to transform one to the other in as few moves as possible by inverting whole numbered rows or whole lettered
columns at once   (as one move).

In an inversion.   any  '''1'''  becomes  '''0''',   and any  '''0'''  becomes  '''1'''  for that whole row or column.

;Task:
Create a program to score for the Flipping bits game.
# The game should create an original random target configuration and a starting configuration.
# Ensure that the starting position is ''never'' the target position.
# The target position must be guaranteed as reachable from the starting position.   (One possible way to do this is to generate the start position by legal flips from a random target position.   The flips will always be reversible back to the target from the given start position).
# The number of moves taken so far should be shown.

Show an example of a short game here, on this page, for a   '''3x3'''   array of bits.

Solution:
class FlipBoard
  def initialize(size)
    raise ArgumentError.new("Invalid board size: #{size}") if size < 2

    @size = size
    @board = Array.new(size**2, 0)

    randomize_board
    loop do
      @target = generate_target
      break unless solved?
    end

    # these are used for validating user input
    @columns = [*'a'...('a'.ord+@size).chr]
    @rows = (1..@size).map(&:to_s)
  end

  ############################################################

  def play
    moves = 0
    puts "your target:", target

    until solved?
      puts "", "move #{moves}:", self
      print "Row/column to flip: "
      ans = $stdin.gets.strip

      if @columns.include? ans
        flip_column @columns.index(ans)
        moves += 1
      elsif @rows.include? ans
        flip_row @rows.index(ans)
        moves += 1
      else
        puts "invalid input: " + ans
      end
    end

    puts "", "you solved the game in #{moves} moves", self
  end

  # the target formation as a string
  def target
    format_array @target
  end

  # the current formation as a string
  def to_s
    format_array @board
  end

  ############################################################
  private

  def solved?
    @board == @target
  end

  # flip a random number of bits on the board
  def randomize_board
    (@size + rand(@size)).times do
      flip_bit rand(@size), rand(@size)
    end
  end

  # generate a random number of flip_row/flip_column calls
  def generate_target
    orig_board = @board.clone
    (@size + rand(@size)).times do
      rand(2).zero? ? flip_row( rand(@size) ) : flip_column( rand(@size) )
    end
    target, @board = @board, orig_board
    target
  end

  def flip_row(row)
    @size.times {|col| flip_bit(row, col)}
  end

  def flip_column(col)
    @size.times {|row| flip_bit(row, col)}
  end

  def flip_bit(row, col)
    @board[@size * row + col] ^= 1
  end

  def format_array(ary)
    str = "   " + @columns.join(" ") + "\n"
    @size.times do |row|
      str << "%2s " % @rows[row] + ary[@size*row, @size].join(" ") + "\n"
    end
    str
  end
end

######################################################################
begin
  FlipBoard.new(ARGV.shift.to_i).play
rescue => e
  puts e.message
end


Floyd's triangle

Floyd's triangle   lists the natural numbers in a right triangle aligned to the left where
* the first row is   '''1'''     (unity)
* successive rows start towards the left with the next number followed by successive naturals listing one more number than the line above.

The first few lines of a Floyd triangle looks like this:

 1
 2  3
 4  5  6
 7  8  9 10
11 12 13 14 15

;Task:
:# Write a program to generate and display here the first   n   lines of a Floyd triangle. (Use   n=5   and   n=14   rows).
:# Ensure that when displayed in a mono-space font, the numbers line up in vertical columns as shown and that only one space separates numbers of the last row.

Solution:
def floyd(rows)
  max = (rows * (rows + 1)) / 2
  widths = ((max - rows + 1)..max).map {|n| n.to_s.length + 1}
  n = 0
  rows.times do |r|
    puts (0..r).map {|i| n += 1; "%#{widths[i]}d" % n}.join
  end
end

floyd(5)
floyd(14)


Four bit adder

"''Simulate''" a four-bit adder.

This design can be realized using four 1-bit full adders.
Each of these 1-bit full adders can be built with two gate. ;

Finally a half adder can be made using an   ''xor''   gate and an   ''and''   gate.

The   ''xor''   gate can be made using two   ''not''s,   two   ''and''s   and one   ''or''.

'''Not''',   '''or'''   and   '''and''',   the only allowed "gates" for the task, can be "imitated" by using the bitwise operators of your language.

If there is not a ''bit type'' in your language, to be sure that the   ''not''   does not "invert" all the other bits of the basic type   (e.g. a byte)   we are not interested in,   you can use an extra   ''nand''   (''and''   then   ''not'')   with the constant   '''1'''   on one input.

Instead of optimizing and reducing the number of gates used for the final 4-bit adder,   build it in the most straightforward way,   ''connecting'' the other "constructive blocks",   in turn made of "simpler" and "smaller" ones.

{|
|+Schematics of the "constructive blocks"
!(Xor gate with ANDs, ORs and NOTs)
!   (A half adder)
!          (A full adder)
!                (A 4-bit adder)
|-
|Xor gate done with ands, ors and nots
|A half adder
|A full adder
|A 4-bit adder
|}

Solutions should try to be as descriptive as possible, making it as easy as possible to identify "connections" between higher-order "blocks".

It is not mandatory to replicate the syntax of higher-order blocks in the atomic "gate" blocks, i.e. basic "gate" operations can be performed as usual bitwise operations, or they can be "wrapped" in a ''block'' in order to expose the same syntax of higher-order blocks, at implementers' choice.

To test the implementation, show the sum of two four-bit numbers (in binary).

Solution:
# returns pair [sum, carry]
def four_bit_adder(a, b)
  a_bits = binary_string_to_bits(a,4)
  b_bits = binary_string_to_bits(b,4)

  s0, c0 = full_adder(a_bits[0], b_bits[0],  0)
  s1, c1 = full_adder(a_bits[1], b_bits[1], c0)
  s2, c2 = full_adder(a_bits[2], b_bits[2], c1)
  s3, c3 = full_adder(a_bits[3], b_bits[3], c2)

  [bits_to_binary_string([s0, s1, s2, s3]), c3.to_s]
end

# returns pair [sum, carry]
def full_adder(a, b, c0)
  s, c = half_adder(c0, a)
  s, c1 = half_adder(s, b)
  [s, _or(c,c1)]
end

# returns pair [sum, carry]
def half_adder(a, b)
  [xor(a, b), _and(a,b)]
end

def xor(a, b)
  _or(_and(a, _not(b)), _and(_not(a), b))
end

# "and", "or" and "not" are Ruby keywords
def _and(a, b)  a & b  end
def _or(a, b)   a | b  end
def _not(a)    ~a & 1  end

def int_to_binary_string(n, length)
  "%0#{length}b" % n
end

def binary_string_to_bits(s, length)
  ("%#{length}s" % s).reverse.chars.map(&:to_i)
end

def bits_to_binary_string(bits)
  bits.map(&:to_s).reverse.join
end

puts " A    B      A      B   C    S  sum"
0.upto(15) do |a|
  0.upto(15) do |b|
    bin_a = int_to_binary_string(a, 4)
    bin_b = int_to_binary_string(b, 4)
    sum, carry = four_bit_adder(bin_a, bin_b)
    puts "%2d + %2d = %s + %s = %s %s = %2d" %
         [a, b, bin_a, bin_b, carry, sum, (carry + sum).to_i(2)]
  end
end


Four is magic

Write a subroutine, function, whatever it may be called in your language, that takes an integer number and returns an English text sequence starting with the English cardinal representation of that integer, the word 'is' and then the English cardinal representation of the count of characters that made up the first word, followed by a comma.

Continue the sequence by using the previous count word as the first word of the next phrase, append 'is' and the cardinal count of the letters in ''that'' word.

Continue until you reach four. Since four has four characters, finish by adding the words 'four is magic' and a period. All integers will eventually wind up at four.

For instance, suppose your are given the integer '''3'''. Convert '''3''' to '''Three''', add ''' is ''', then the cardinal character count of three, or '''five''', with a comma to separate if from the next phrase. Continue the sequence '''five is four,''' (five has four letters), and finally, '''four is magic.'''

      '''Three is five, five is four, four is magic.'''

For reference, here are outputs for 0 through 9.

      Zero is four, four is magic.
      One is three, three is five, five is four, four is magic.
      Two is three, three is five, five is four, four is magic.
      Three is five, five is four, four is magic.
      Four is magic.
      Five is four, four is magic.
      Six is three, three is five, five is four, four is magic.
      Seven is five, five is four, four is magic.
      Eight is five, five is four, four is magic.
      Nine is four, four is magic.

;Some task guidelines:
:* You may assume the input will only contain integer numbers.
:* Cardinal numbers between 20 and 100 may use either hyphens or spaces as word separators but they must use a word separator. ('''23''' is '''twenty three''' or '''twenty-three''' not '''twentythree'''.)
:* Cardinal number conversions should follow the  English short scale. (billion is 1e9, trillion is 1e12, etc.)
:* Cardinal numbers should not include commas. ('''20140''' is '''twenty thousand one hundred forty''' not '''twenty thousand, one hundred forty'''.)
:* When converted to a string, '''100''' should be '''one hundred''', not '''a hundred''' or '''hundred''', '''1000''' should be '''one thousand''', not '''a thousand''' or '''thousand'''.
:* When converted to a string, there should be no '''and''' in the cardinal string. '''130''' should be '''one hundred thirty''' not '''one hundred and thirty'''.
:* When counting characters, count ''all'' of the characters in the cardinal number including spaces and hyphens. '''One hundred fifty-one''' should be '''21''' not '''18'''.
:* The output should follow the format "N is K, K is M, M is ... four is magic." (unless the input is 4, in which case the output should simply be "four is magic.")
:* The output can either be the return value from the function, or be displayed from within the function.
:* You are encouraged, though not mandated to use proper sentence capitalization.
:* You may optionally support negative numbers. '''-7''' is '''negative seven'''.
:* Show the output here for a small representative sample of values, at least 5 but no more than 25. You are free to choose which which numbers to use for output demonstration.

You can choose to use a library, (module, external routine, whatever) to do the cardinal conversions as long as the code is easily and freely available to the public.

If you roll your own, make the routine accept at minimum any integer from 0 up to 999999. If you use a pre-made library, support at least up to unsigned 64 bit integers. (or the largest integer supported in your language if it is less.)

Four is magic is a popular code-golf task. '''This is not code golf.''' Write legible, idiomatic and well formatted code.

;Related tasks:
:*   [[Four is the number of_letters in the ...]]
:*   [[Look-and-say sequence]]
:*   [[Number names]]
:*   [[Self-describing numbers]]
:*   [[Summarize and say sequence]]
:*   [[Spelling of ordinal numbers]]
:*   [[De Bruijn sequences]]

Solution:
module NumberToWord

  NUMBERS = {  # taken from https://en.wikipedia.org/wiki/Names_of_large_numbers#cite_ref-a_14-3
    1 => 'one',
    2 => 'two',
    3 => 'three',
    4 => 'four',
    5 => 'five',
    6 => 'six',
    7 => 'seven',
    8 => 'eight',
    9 => 'nine',
    10 => 'ten',
    11 => 'eleven',
    12 => 'twelve',
    13 => 'thirteen',
    14 => 'fourteen',
    15 => 'fifteen',
    16 => 'sixteen',
    17 => 'seventeen',
    18 => 'eighteen',
    19 => 'nineteen',
    20 => 'twenty',
    30 => 'thirty',
    40 => 'forty',
    50 => 'fifty',
    60 => 'sixty',
    70 => 'seventy',
    80 => 'eighty',
    90 => 'ninety',
    100 => 'hundred',
    1000 => 'thousand',
    10 ** 6 => 'million',
    10 ** 9 => 'billion',
    10 ** 12 => 'trillion',
    10 ** 15 => 'quadrillion',
    10 ** 18 => 'quintillion',
    10 ** 21 => 'sextillion',
    10 ** 24 => 'septillion',
    10 ** 27 => 'octillion',
    10 ** 30 => 'nonillion',
    10 ** 33 => 'decillion'}.reverse_each.to_h

  refine Integer do
    def to_english
      return 'zero' if i.zero?
      words =  self < 0 ? ['negative'] : []
      i = self.abs
      NUMBERS.each do |k, v|
        if k <= i then
          times = i/k
          words << times.to_english if k >= 100
          words << v
          i -= times * k
        end
        return words.join(" ") if i.zero?
      end
    end
  end

end

using  NumberToWord

def magic4(n)
  words = []
  until n == 4
    s = n.to_english
    n = s.size
    words << "#{s} is #{n.to_english}"
  end
  words << "four is magic."
  words.join(", ").capitalize
end

[0, 4, 6, 11, 13, 75, 337, -164, 9_876_543_209].each{|n| puts magic4(n) }


Fusc sequence

Definitions:
The   '''fusc'''   integer sequence is defined as:
::*   fusc(0) = 0
::*   fusc(1) = 1
::*   for '''n'''>1,   the   '''n'''th   term is defined as:
::::*   if   '''n'''   is       even;     fusc(n) = fusc(n/2)
::::*   if   '''n'''   is   odd;     fusc(n) = fusc((n-1)/2)   +   fusc((n+1)/2)

Note that MathWorld's definition starts with unity, not zero.   This task will be using the OEIS' version   (above).

;An observation:
:::::*   fusc(A) = fusc(B)

where   '''A'''   is some non-negative integer expressed in binary,   and
where   '''B'''   is the binary value of   '''A'''   reversed.

Fusc numbers are also known as:
::*   fusc function   (named by Dijkstra, 1982)
::*   Stern's Diatomic series   (although it starts with unity, not zero)
::*   Stern-Brocot sequence   (although it starts with unity, not zero)

;Task:
::*   show the first   '''61'''   fusc numbers (starting at zero) in a horizontal format.
::*   show the fusc number (and its index) whose length is greater than any previous fusc number length.
::::*   (the length is the number of decimal digits when the fusc number is expressed in base ten.)
::*   show all numbers with commas   (if appropriate).
::*   show all output here.

;Related task:
::*   RosettaCode Stern-Brocot sequence

;Also see:
::*   the MathWorld entry:   Stern's Diatomic Series.
::*   the OEIS      entry:   A2487.

Solution:
fusc = Enumerator.new do |y|
  y << 0
  y << 1
  arr = [0,1]
  2.step do |n|
    res = n.even? ? arr[n/2] : arr[(n-1)/2] + arr[(n+1)/2]
    y   << res
    arr << res
  end
end

fusc_max_digits = Enumerator.new do |y|
   cur_max, cur_exp = 0, 0
   0.step do |i|
      f = fusc.next
      if f >= cur_max
        cur_exp += 1
        cur_max = 10**cur_exp
        y << [i, f]
      end
   end
end

puts fusc.take(61).join(" ")
fusc_max_digits.take(6).each{|pair| puts "%15s : %s" % pair }


Gapful numbers

Numbers   (positive integers expressed in base ten)   that are (evenly) divisible by the number formed by the
first and last digit are known as   '''gapful numbers'''.

''Evenly divisible''   means divisible with   no   remainder.

All   one-   and two-digit   numbers have this property and are trivially excluded.   Only
numbers    >=  '''100'''   will be considered for this Rosetta Code task.

;Example:
'''187'''   is a   '''gapful'''   number because it is evenly divisible by the
number   '''17'''   which is formed by the first and last decimal digits
of    '''187'''.

About   7.46%   of positive integers are   ''gapful''.

;Task:
:*   Generate and show all sets of numbers (below) on one line (horizontally) with a title,   here on this page
:*   Show the first   '''30'''   gapful numbers
:*   Show the first   '''15'''   gapful numbers    >=           '''1,000,000'''
:*   Show the first   '''10'''   gapful numbers    >=                               '''1,000,000,000'''

;Related tasks:
:*   Harshad or Niven series.
:*   palindromic gapful numbers.
:*   largest number divisible by its digits.

;Also see:
:*   The OEIS entry:   A108343 gapful numbers.
:*   numbersaplenty gapful numbers

Solution:
class Integer
  def gapful?
    a = digits
    self % (a.last*10 + a.first) == 0
  end
end

specs = {100 => 30, 1_000_000 => 15, 1_000_000_000 => 10, 7123 => 25}

specs.each do |start, num|
  puts "first #{num} gapful numbers >= #{start}:"
  p (start..).lazy.select(&:gapful?).take(num).to_a
end


Gauss-Jordan matrix inversion

Invert matrix   '''A'''   using Gauss-Jordan method.

'''A'''   being an   '''n''' x '''n'''   matrix.

Solution:
require 'matrix'

m = Matrix[[-1, -2, 3, 2],
           [-4, -1, 6, 2],
           [ 7, -8, 9, 1],
           [ 1, -2, 1, 3]]

pp m.inv.row_vectors


Gaussian elimination

Solve   '''Ax=b'''   using Gaussian elimination then backwards substitution.

'''A'''   being an   '''n''' by '''n'''   matrix.

Also,   '''x''' and '''b'''   are   '''n''' by '''1'''   vectors.

To improve accuracy, please use partial pivoting and scaling.

;See also:
:*   the Wikipedia entry:   Gaussian elimination

Solution:
require 'bigdecimal/ludcmp'
include LUSolve

BigDecimal::limit(30)

a = [1.00, 0.00, 0.00, 0.00, 0.00, 0.00,
     1.00, 0.63, 0.39, 0.25, 0.16, 0.10,
     1.00, 1.26, 1.58, 1.98, 2.49, 3.13,
     1.00, 1.88, 3.55, 6.70, 12.62, 23.80,
     1.00, 2.51, 6.32, 15.88, 39.90, 100.28,
     1.00, 3.14, 9.87, 31.01, 97.41, 306.02].map{|i|BigDecimal(i,16)}
b = [-0.01, 0.61, 0.91, 0.99, 0.60, 0.02].map{|i|BigDecimal(i,16)}

n = 6
zero = BigDecimal("0.0")
one  = BigDecimal("1.0")

lusolve(a, b, ludecomp(a, n, zero,one), zero).each{|v| puts v.to_s('F')[0..20]}


Generate Chess960 starting position

Bobby Fischer.  Unlike other variants of the game, Chess960 does not require a different material, but instead relies on a random initial position, with a few constraints:

* as in the standard chess game, all eight white pawns must be placed on the second rank.
* White pieces must stand on the first rank as in the standard game, in random column order but with the two following constraints:
** the bishops must be placed on opposite color squares (i.e. they must be an odd number of spaces apart or there must be an even number of spaces between them)
** the King must be between two rooks (with any number of other pieces between them all)
* Black pawns and pieces must be placed respectively on the seventh and eighth ranks, mirroring the white pawns and pieces, just as in the standard game.  (That is, their positions are not independently randomized.)

With those constraints there are '''960''' possible starting positions, thus the name of the variant.

;Task:
The purpose of this task is to write a program that can randomly generate any one of the 960 Chess960 initial positions. You will show the result as the first rank displayed with Chess symbols in Unicode:  or with the letters '''K'''ing '''Q'''ueen '''R'''ook '''B'''ishop k'''N'''ight.

Solution:
pieces = %i(♔ ♕ ♘ ♘ ♗ ♗ ♖ ♖)
regexes = [/♗(..)*♗/, /♖.*♔.*♖/]
row = pieces.shuffle.join until regexes.all?{|re| re.match(row)}
puts row


Generate random chess position

Generate a random chess position in FEN format.

The position does not have to be realistic or even balanced,  but it must comply to the following rules:
:* there is one and only one king of each color  (one black king and one white king);
:* the kings must not be placed on adjacent squares;
:* there can not be any pawn in the promotion square  (no white pawn in the eighth rank, and no black pawn in the first rank);
:* including the kings, up to 32 pieces of either color can be placed.
:* There is no requirement for material balance between sides.
:* The picking of pieces does not have to comply to a regular chess set --- there can be five knights, twenty rooks, whatever ... as long as the total number of pieces do not exceed thirty-two.
:* it is white's turn.
:* It's assumed that both sides have lost castling rights and that there is no possibility for   ''en passant''   (the FEN should thus end in w - - 0 1).

No requirement is made regarding the probability distribution of your method, but your program should be able to span a reasonably representative sample of all possible positions.  For instance, programs that would always generate positions with say five pieces on the board, or with kings on a corner, would not be considered truly random.

Solution:
def hasNK( board, a, b )
    for g in -1 .. 1
        for f in -1 .. 1
            aa = a + f; bb = b + g
            if aa.between?( 0, 7 ) && bb.between?( 0, 7 )
                p = board[aa + 8 * bb]
                if p == "K" || p == "k"; return true; end
            end
        end
    end
    return false
end
def generateBoard(  board, pieces  )
    while( pieces.length > 1 )
        p = pieces[pieces.length - 1]
        pieces = pieces[0...-1]
        while( true )
            a = rand( 8 ); b = rand( 8 )
            if ( ( b == 0 || b == 7 ) && ( p == "P" || p == "p" ) ) ||
               ( ( p == "k" || p == "K" ) && hasNK( board, a, b ) ); next; end
            if board[a + b * 8] == nil; break;end
        end
        board[a + b * 8] = p
    end
end
pieces = "ppppppppkqrrbbnnPPPPPPPPKQRRBBNN"
for i in 0 .. 10
    e = pieces.length - 1
    while e > 0
        p = rand( e ); t = pieces[e];
        pieces[e] = pieces[p]; pieces[p] = t; e -= 1
    end
end
board = Array.new( 64 ); generateBoard( board, pieces )
puts
e = 0
for j in 0 .. 7
    for i in 0 .. 7
        if board[i + 8 * j] == nil; e += 1
        else
            if e > 0; print( e ); e = 0; end
            print( board[i + 8 * j] )
        end
    end
    if e > 0; print( e ); e = 0; end
    if j < 7; print( "/" ); end
end
print( " w - - 0 1\n" )
for j in 0 .. 7
    for i in 0 .. 7
        if board[i + j * 8] == nil; print( "." )
        else print( board[i + j * 8] ); end
    end
    puts
end


Generator/Exponential

A generator is an executable entity (like a function or procedure) that contains code that yields a sequence of values, one at a time, so that each time you call the generator, the next value in the sequence is provided.

Generators are often built on top of coroutines or objects so that the internal state of the object is handled "naturally".

Generators are often used in situations where a sequence is potentially infinite, and where it is possible to construct the next value of the sequence with only minimal state.

;Task:
* Create a function that returns a generation of the m'th powers of the positive integers starting from zero, in order, and without obvious or simple upper limit. (Any upper limit to the generator should not be stated in the source but should be down to factors such as the languages natural integer size limit or computational time/size).
* Use it to create a generator of:
:::*   Squares.
:::*   Cubes.
* Create a new generator that filters all cubes from the generator of squares.
* Drop the first 20 values from this last generator of filtered results, and then show the next 10 values.

Note that this task ''requires'' the use of generators in the calculation of the result.

;Also see:
* Generator

Solution:
# This solution cheats and uses only one generator!

def powers(m)
  return enum_for(__method__, m) unless block_given?
  0.step{|n| yield n**m}
end

def squares_without_cubes
  return enum_for(__method__) unless block_given?

  cubes = powers(3)
  c = cubes.next
  powers(2) do |s|
    c = cubes.next while c < s
    yield s unless c == s
  end
end

p squares_without_cubes.take(30).drop(20)
# p squares_without_cubes.lazy.drop(20).first(10)   # Ruby 2.0+


Generator/Exponential

Solution:
def filtered(s1, s2)
  return enum_for(__method__, s1, s2) unless block_given?
  v, f = s1.next, s2.next
  loop do
    v > f and f = s2.next and next
    v < f and yield v
    v = s1.next
  end
end

squares, cubes = powers(2), powers(3)
f = filtered(squares, cubes)
p f.take(30).last(10)
# p f.lazy.drop(20).first(10)   # Ruby 2.0+


Giuga numbers

Definition
A '''Giuga number''' is a composite number '''n''' which is such that each of its distinct prime factors
'''f''' divide (n/f - 1) exactly.

All known Giuga numbers are even though it is not known for certain that there are no odd examples.

;Example
30 is a Giuga number because its distinct prime factors are 2, 3 and 5 and:
* 30/2 - 1 = 14 is divisible by 2
* 30/3 - 1 = 9 is divisible by 3
* 30/5 - 1 = 5 is divisible by 5

;Task
Determine and show here the first four Giuga numbers.

;Stretch
Determine the fifth Giuga number and any more you have the patience for.

;References

* Wikipedia: Giuga number
* OEIS:A007850 - Giuga numbers

Solution:
require 'prime'

giuga = (1..).lazy.select do |n|
  pd = n.prime_division
  pd.sum{|_, d| d} > 1 &&  #composite
  pd.all?{|f, _| (n/f - 1) % f == 0}
end

p giuga.take(4).to_a


Globally replace text in several files

Replace every occurring instance of a piece of text in a group of text files with another one.

For this task we want to replace the text   "'''Goodbye London!'''"   with   "'''Hello New York!'''"   for a list of files.

Solution:
Like Perl:

ruby -pi -e "gsub('Goodbye London!', 'Hello New York!')" a.txt b.txt c.txt


Gray code

Karnaugh maps in order from left to right or top to bottom.
Create functions to encode a number to and decode a number from Gray code.

Display the normal binary representations, Gray code representations, and decoded Gray code values for all 5-bit binary numbers (0-31 inclusive, leading 0's not necessary).

There are many possible Gray codes. The following encodes what is called "binary reflected Gray code."

Encoding (MSB is bit 0, b is binary, g is Gray code):

if b[i-1] = 1
   g[i] = not b[i]
else
   g[i] = b[i]

Or:

g = b xor (b logically right shifted 1 time)

Decoding (MSB is bit 0, b is binary, g is Gray code):

b[0] = g[0]

for other bits:
b[i] = g[i] xor b[i-1]

;Reference
* Converting Between Gray and Binary Codes. It includes step-by-step animations.

Solution:
class Integer
  # Converts a normal integer to a Gray code.
  def to_gray
    raise Math::DomainError, "integer is negative" if self < 0
    self ^ (self >> 1)
  end

  # Converts a Gray code to a normal integer.
  def from_gray
    raise Math::DomainError, "integer is negative" if self < 0
    recurse = proc do |i|
      next 0 if i == 0
      o = recurse[i >> 1] << 1
      o | (i[0] ^ o[1])
    end
    recurse[self]
  end
end

(0..31).each do |number|
  encoded = number.to_gray
  decoded = encoded.from_gray
  printf "%2d : %5b => %5b => %5b : %2d\n",
         number, number, encoded, decoded, decoded
end


Greatest subsequential sum

Given a sequence of integers, find a continuous subsequence which maximizes the sum of its elements, that is, the elements of no other single subsequence add up to a value larger than this one.

An empty subsequence is considered to have the sum of   '''0''';   thus if all elements are negative, the result must be the empty sequence.

Solution:
[ [1, 2, 3, 4, 5, -8, -9, -20, 40, 25, -5],
  [-1, -2, 3, 5, 6, -2, -1, 4, -4, 2, -1],
  [-1, -2, -3, -4, -5],
  []
].each do |input|
  puts "\nInput seq: #{input}"
  puts "  Max sum: %d\n   Subseq: %s" % subarray_sum(input)
end


Greedy algorithm for Egyptian fractions

An   Egyptian fraction   is the sum of distinct unit fractions such as:

::::   \tfrac{1}{2} + \tfrac{1}{3} + \tfrac{1}{16} \,(= \tfrac{43}{48})

Each fraction in the expression has a numerator equal to   '''1'''   (unity)   and a denominator that is a positive integer,   and all the denominators are distinct   (i.e., no repetitions).

Fibonacci's   Greedy algorithm for Egyptian fractions   expands the fraction     \tfrac{x}{y}     to be represented by repeatedly performing the replacement

::::   \frac{x}{y} = \frac{1}{\lceil y/x\rceil} + \frac{(-y)\!\!\!\!\mod x}{y\lceil y/x\rceil}

(simplifying the 2nd term in this replacement as necessary, and where     \lceil x \rceil     is the   ''ceiling''   function).

For this task,   Proper and improper fractions   must be able to be expressed.

Proper  fractions   are of the form    \tfrac{a}{b}    where    a    and    b    are positive integers, such that    a < b,     and

improper fractions are of the form    \tfrac{a}{b}    where    a    and    b    are positive integers, such that    ''a'' >= ''b''.

(See the REXX programming example to view one method of expressing the whole number part of an improper fraction.)

For improper fractions, the integer part of any improper fraction should be first isolated and shown preceding the Egyptian unit fractions, and be surrounded by square brackets [''n''].

;Task requirements:
*   show the Egyptian fractions for:  \tfrac{43}{48}  and  \tfrac{5}{121}  and  \tfrac{2014}{59}
*   for all proper fractions,    \tfrac{a}{b}    where    a    and    b    are positive one-or two-digit (decimal) integers, find and show an Egyptian fraction that has:
::*   the largest number of terms,
::*   the largest denominator.
*   for all one-, two-, and three-digit integers,   find and show (as above).     {extra credit}

;Also see:
*   Wolfram MathWorld(tm) entry: Egyptian fraction

Solution:
def ef(fr)
  ans = []
  if fr >= 1
    return [[fr.to_i], Rational(0, 1)]  if fr.denominator == 1
    intfr = fr.to_i
    ans, fr = [intfr], fr - intfr
  end
  x, y = fr.numerator, fr.denominator
  while x != 1
    ans << Rational(1, (1/fr).ceil)
    fr = Rational(-y % x, y * (1/fr).ceil)
    x, y = fr.numerator, fr.denominator
  end
  ans << fr
end

for fr in [Rational(43, 48), Rational(5, 121), Rational(2014, 59)]
  puts '%s => %s' % [fr, ef(fr).join(' + ')]
end

lenmax = denommax = [0]
for b in 2..99
  for a in 1...b
    fr = Rational(a,b)
    e = ef(fr)
    elen, edenom = e.length, e[-1].denominator
    lenmax = [elen, fr] if elen > lenmax[0]
    denommax = [edenom, fr] if edenom > denommax[0]
  end
end
puts 'Term max is %s with %i terms' % [lenmax[1], lenmax[0]]
dstr = denommax[0].to_s
puts 'Denominator max is %s with %i digits' % [denommax[1], dstr.size], dstr


Hailstone sequence

The Hailstone sequence of numbers can be generated from a starting positive integer,   n   by:
*   If   n   is     '''1'''     then the sequence ends.
*   If   n   is   '''even''' then the next   n   of the sequence    = n/2
*   If   n   is   '''odd'''    then the next   n   of the sequence    = (3 * n) + 1

The (unproven) Collatz conjecture is that the hailstone sequence for any starting number always terminates.

This sequence was named by Lothar Collatz in 1937   (or possibly in 1939),   and is also known as (the):
:::*   hailstone sequence,   hailstone numbers
:::*   3x + 2 mapping,   3n + 1 problem
:::*   Collatz sequence
:::*   Hasse's algorithm
:::*   Kakutani's problem
:::*   Syracuse algorithm,   Syracuse problem
:::*   Thwaites conjecture
:::*   Ulam's problem

The hailstone sequence is also known as   ''hailstone numbers''   (because the values are usually subject to multiple descents and ascents like hailstones in a cloud).

;Task:
# Create a routine to generate the hailstone sequence for a number.
# 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
# Show the number less than 100,000 which has the longest hailstone sequence together with that sequence's length.    (But don't show the actual sequence!)

;See also:
*   xkcd (humourous).
*   The Notorious Collatz conjecture Terence Tao, UCLA (Presentation, pdf).
*   The Simplest Math Problem No One Can Solve Veritasium (video, sponsored).

Solution: This program uses new methods (Integer#even? and Enumerable#max_by) from Ruby 1.8.7.


Hailstone sequence

Solution:
module Hailstone
  ListNode = Struct.new(:value, :size, :succ) do
    def each
      node = self
      while node
        yield node.value
        node = node.succ
      end
    end
  end

  @@sequence = {1 => ListNode[1,1]}

  module_function

  def sequence(n)
    unless @@sequence[n]
      m, ary = n, []
      until succ = @@sequence[m]
        ary << m
        m = m.even? ? (m / 2) : (3 * m + 1)
      end
      ary.reverse_each do |m|
        @@sequence[m] = succ = ListNode[m, succ.size + 1, succ]
      end
    end
    @@sequence[n]
  end
end

puts "for n = 27, show sequence length and first and last 4 elements"
hs27 = Hailstone.sequence(27).entries
p [hs27.size, hs27[0..3], hs27[-4..-1]]

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


Harmonic series

{{Wikipedia|Harmonic number}}

In mathematics, the '''n-th''' harmonic number is the sum of the reciprocals of the first '''n''' natural numbers:

'''H''n'' = 1 + 1/2 + 1/3 + ... + 1/n'''

The series of harmonic numbers thus obtained is often loosely referred to as the harmonic series.

Harmonic numbers are closely related to the Euler-Mascheroni constant.

The harmonic series is divergent, albeit quite slowly, and grows toward infinity.

;Task
* Write a function (routine, procedure, whatever it may be called in your language) to generate harmonic numbers.
* Use that procedure to show the values of the first 20 harmonic numbers.
* Find and show the position in the series of the first value greater than the integers 1 through 5

;Stretch
* Find and show the position in the series of the first value greater than the integers 6 through 10

;Related
* [[Egyptian fractions]]

Solution:
harmonics = Enumerator.new do |y|
  res = 0
  (1..).each {|n| y << res += Rational(1, n) }
end

n = 20
The first #{n} harmonics (as rationals):""
harmonics.take(n).each_slice(5){|slice| puts "%20s"*slice.size % slice }

puts
milestones = (1..10).to_a
harmonics.each.with_index(1) do |h,i|
  if h > milestones.first then
    puts "The first harmonic number > #{milestones.shift} is #{h.to_f} at position #{i}"
  end
  break if milestones.empty?
end


Harshad or Niven series

The Harshad or Niven numbers are positive integers >= 1 that are divisible by the sum of their digits.

For example,   '''42'''   is a Harshad number as   '''42'''   is divisible by   ('''4''' + '''2''')   without remainder.

Assume that the series is defined as the numbers in increasing order.

;Task:
The task is to create a function/method/procedure to generate successive members of the Harshad sequence.

Use it to:
::*   list the first '''20''' members of the sequence,   and
::*   list the first Harshad number greater than '''1000'''.

Show your output here.

;Related task
:*   Increasing gaps between consecutive Niven numbers

;See also
*    OEIS: A005349

Solution:
harshad = 1.step.lazy.select { |n| n % n.digits.sum == 0 }

puts "The first 20 harshard numbers are: \n#{ harshad.first(20) }"
puts "The first harshard number > 1000 is #{ harshad.find { |n| n > 1000 } }"


Hash join

{| class="wikitable"
|-
! Input
! Output
|-
|

{| style="border:none; border-collapse:collapse;"
|-
| style="border:none" | ''A'' =
| style="border:none" |

{| class="wikitable"
|-
! Age !! Name
|-
| 27 || Jonah
|-
| 18 || Alan
|-
| 28 || Glory
|-
| 18 || Popeye
|-
| 28 || Alan
|}

| style="border:none; padding-left:1.5em;" rowspan="2" |
| style="border:none" | ''B'' =
| style="border:none" |

{| class="wikitable"
|-
! Character !! Nemesis
|-
| Jonah || Whales
|-
| Jonah || Spiders
|-
| Alan || Ghosts
|-
| Alan || Zombies
|-
| Glory || Buffy
|}

|-
| style="border:none" | ''jA'' =
| style="border:none" | Name (i.e. column 1)

| style="border:none" | ''jB'' =
| style="border:none" | Character (i.e. column 0)
|}

|

{| class="wikitable" style="margin-left:1em"
|-
! A.Age !! A.Name !! B.Character !! B.Nemesis
|-
| 27 || Jonah || Jonah || Whales
|-
| 27 || Jonah || Jonah || Spiders
|-
| 18 || Alan || Alan || Ghosts
|-
| 18 || Alan || Alan || Zombies
|-
| 28 || Glory || Glory || Buffy
|-
| 28 || Alan || Alan || Ghosts
|-
| 28 || Alan || Alan || Zombies
|}

|}

The order of the rows in the output table is not significant.
If you're using numerically indexed arrays to represent table rows (rather than referring to columns by name), you could represent the output rows in the form [[27, "Jonah"], ["Jonah", "Whales"]].

Solution:
def hashJoin(table1, index1, table2, index2)
  # hash phase
  h = table1.group_by {|s| s[index1]}
  h.default = []
  # join phase
  table2.collect {|r|
    h[r[index2]].collect {|s| [s, r]}
  }.flatten(1)
end

table1 = [[27, "Jonah"],
          [18, "Alan"],
          [28, "Glory"],
          [18, "Popeye"],
          [28, "Alan"]]
table2 = [["Jonah", "Whales"],
          ["Jonah", "Spiders"],
          ["Alan", "Ghosts"],
          ["Alan", "Zombies"],
          ["Glory", "Buffy"]]

hashJoin(table1, 1, table2, 0).each { |row| p row }


Haversine formula

{{Wikipedia}}

The '''haversine formula''' is an equation important in navigation, giving great-circle distances between two points on a sphere from their longitudes and latitudes.

It is a special case of a more general formula  in spherical trigonometry, the '''law of haversines''', relating the sides and angles of spherical "triangles".

;Task:
Implement a great-circle distance function, or use a library function,
to show the great-circle distance between:
* Nashville International Airport (BNA)   in Nashville, TN, USA,   which is:
    '''N''' 36deg7.2',   '''W''' 86deg40.2'     (36.12,   -86.67)           -and-
* Los Angeles International Airport (LAX)  in Los Angeles, CA, USA,   which is:
    '''N''' 33deg56.4',  '''W''' 118deg24.0'    (33.94,  -118.40)

User Kaimbridge clarified on the Talk page:

 -- 6371.0 km is the authalic radius based on/extracted from surface area;
 -- 6372.8 km is an approximation of the radius of the average circumference
    (i.e., the average great-elliptic or great-circle radius), where the
     boundaries are the meridian (6367.45 km) and the equator (6378.14 km).

Using either of these values results, of course, in differing distances:

 6371.0 km -> 2886.44444283798329974715782394574671655 km;
 6372.8 km -> 2887.25995060711033944886005029688505340 km;
 (results extended for accuracy check:  Given that the radii are only
  approximations anyways, .01'  1.0621333 km and .001"  .00177 km,
  practical precision required is certainly no greater than about
  .0000001----i.e., .1 mm!)

As distances are segments of great circles/circumferences, it is
recommended that the latter value (r = 6372.8 km) be used (which
most of the given solutions have already adopted, anyways).

Most of the examples below adopted Kaimbridge's recommended value of
6372.8 km for the earth radius.  However, the derivation of this
ellipsoidal quadratic mean radius
is wrong (the averaging over azimuth is biased).  When applying these
examples in real applications, it is better to use the
mean earth radius,
6371 km.  This value is recommended by the International Union of
Geodesy and Geophysics and it minimizes the RMS relative error between the
great circle and geodesic distance.

Solution:
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 deg2rad(lat, long)
  [lat * PI / 180, long * PI / 180]
end

bna = [36.12, -86.67]
lax = [33.94, -118.4]

puts "%.1f" % spherical_distance(bna, lax)


Haversine formula

Solution:
include Math

def haversine(lat1, lon1, lat2, lon2)
    r = 6372.8        # Earth radius in kilometers
    deg2rad = PI/180  # convert degress to radians

    dLat = (lat2 - lat1) * deg2rad
    dLon = (lon2 - lon1) * deg2rad
    lat1 = lat1 * deg2rad
    lat2 = lat2 * deg2rad

    a = sin(dLat / 2)**2 + cos(lat1) * cos(lat2) * sin(dLon / 2)**2
    c = 2 * asin(sqrt(a))
    r * c
end

puts "distance is #{haversine(36.12, -86.67, 33.94, -118.40)} km "


Here document

A   ''here document''    (or "heredoc")   is a way of specifying a text block, preserving the line breaks, indentation and other whitespace within the text.

Depending on the language being used, a   ''here document''   is constructed using a command followed by "<<" (or some other symbol) followed by a token string.

The text block will then start on the next line, and will be followed by the chosen token at the beginning of the following line, which is used to mark the end of the text block.

;Task:
Demonstrate the use of   ''here documents''   within the language.

;Related task:
*   [[Documentation]]

Solution:
address = <<END
1, High Street,
#{town_name},
West Midlands.
WM4 5HD.
END


Heronian triangles

Hero's formula for the area of a triangle given the length of its three sides    ''a'',   ''b'',   and   ''c''   is given by:

:::: A = \sqrt{s(s-a)(s-b)(s-c)},

where   ''s''   is half the perimeter of the triangle; that is,

:::: s=\frac{a+b+c}{2}.

'''Heronian triangles'''
are triangles whose sides ''and area'' are all integers.
: An example is the triangle with sides   '''3, 4, 5'''   whose area is   '''6'''   (and whose perimeter is   '''12''').

Note that any triangle whose sides are all an integer multiple of   '''3, 4, 5''';   such as   '''6, 8, 10,'''   will also be a Heronian triangle.

Define a '''Primitive Heronian triangle''' as a Heronian triangle where the greatest common divisor
of all three sides is   '''1'''   (unity).

This will exclude, for example, triangle   '''6, 8, 10.'''

;Task:
# Create a named function/method/procedure/... that implements Hero's formula.
# Use the function to generate all the ''primitive'' Heronian triangles with sides <= 200.
# Show the count of how many triangles are found.
# Order the triangles by first increasing area, then by increasing perimeter, then by increasing maximum side lengths
# Show the first ten ordered triangles in a table of sides, perimeter, and area.
# Show a similar ordered table for those triangles with area = 210

Show all output here.

'''Note''': when generating triangles it may help to restrict a <= b <= c

Solution:
class Triangle
  def self.valid?(a,b,c)      # class method
    short, middle, long = [a, b, c].sort
    short + middle > long
  end

  attr_reader :sides, :perimeter, :area

  def initialize(a,b,c)
    @sides = [a, b, c].sort
    @perimeter = a + b + c
    s = @perimeter / 2.0
    @area = Math.sqrt(s * (s - a) * (s - b) * (s - c))
  end

  def heronian?
    area == area.to_i
  end

  def <=>(other)
    [area, perimeter, sides] <=> [other.area, other.perimeter, other.sides]
  end

  def to_s
    "%-11s%6d%8.1f" % [sides.join('x'), perimeter, area]
  end
end

max, area = 200, 210
prim_triangles = []
1.upto(max) do |a|
  a.upto(max) do |b|
    b.upto(max) do |c|
      next if a.gcd(b).gcd(c) > 1
      prim_triangles << Triangle.new(a, b, c) if Triangle.valid?(a, b, c)
    end
  end
end

sorted = prim_triangles.select(&:heronian?).sort

puts "Primitive heronian triangles with sides upto #{max}: #{sorted.size}"
puts "\nsides       perim.   area"
puts sorted.first(10).map(&:to_s)
puts "\nTriangles with an area of: #{area}"
sorted.each{|tr| puts tr if tr.area == area}


Hex words

Definition
For the purposes of this task a '''hex word''' means a word which (in lower case form) consists entirely of the letters '''a, b, c, d, e''' and '''f'''.

;Task
Using unixdict.txt, find all hex words with '''4''' letters or more.

Convert each such word to its decimal equivalent and compute its base 10 digital root.

Display all three in increasing order of digital root and show the total count of such words.

Keeping only words which contain at least '''4''' distinct letters, display the same statistics but in decreasing order of decimal equivalent together with their total count.

Solution:
def report(a)
  puts
  a.each {|hexword| puts "%6s  %8d  %d" % hexword}
  puts "Total count of these words: #{a.size}"
end

hexwords = File.readlines("unixdict.txt", chomp: true).reject{|w| w.size < 4 || w.match?(/[^abcdef]/) }
res = hexwords.map{|hw| [hw, hw.to_i(16), 1 + (hw.to_i(16) - 1) % 9]}.sort_by(&:last)
report( res )
report( res.reject{|hw| hw[0].chars.uniq.size < 4}.sort_by{|w| -w[1]} )


Hickerson series of almost integers

The following function,   due to D. Hickerson,   is said to generate "Almost integers" by the
"Almost Integer" page of Wolfram MathWorld,   (December 31 2013).   (See formula numbered   '''51'''.)

The function is:           h(n) = {\operatorname{n}!\over2(\ln{2})^{n+1}}

It is said to produce "almost integers" for   '''n'''   between   '''1'''   and   '''17'''.
The purpose of the task is to verify this assertion.

Assume that an "almost integer" has '''either a nine or a zero as its first digit after the decimal point''' of its decimal string representation

;Task:
Calculate all values of the function checking and stating which are "almost integers".

Note: Use extended/arbitrary precision numbers in your calculation if necessary to ensure you have adequate precision of results as for example:
                h(18) = 3385534663256845326.39...

Solution:
require "bigdecimal"

LN2 = BigMath::log(2,16)  #Use LN2 = Math::log(2) to see the difference with floats
FACTORIALS = Hash.new{|h,k| h[k] = k * h[k-1]}
FACTORIALS[0] = 1

def hickerson(n)
  FACTORIALS[n] / (2 * LN2 ** (n+1))
end

def nearly_int?(n)
  int = n.round
  n.between?(int - 0.1, int + 0.1)
end

1.upto(17) do |n|
  h = hickerson(n)
  str = nearly_int?(h) ? "nearly integer" : "NOT nearly integer"
  puts "n:%3i h: %s\t%s" % [n, h.to_s('F')[0,25], str] #increase the 25 to print more digits, there are 856 of them
end


History variables

''Storing the history of objects in a program is a common task.
Maintaining the history of an object in a program has traditionally required programmers either to write specific code for handling the historical data, or to use a library which supports history logging.''

''History variables are variables in a programming language which store not only their current value, but also the values they have contained in the past. Some existing languages do provide support for history variables. However these languages typically have many limits and restrictions on use of history variables.
''

"History Variables:
The Semantics, Formal Correctness, and Implementation of History Variables
in an Imperative Programming Language" by Mallon and Takaoka

Concept also discussed on LtU and Patents.com.

;Task:
Demonstrate History variable support:
* enable history variable support (if needed)
* define a history variable
* assign three values
* non-destructively display the history
* recall the three values.

For extra points, if the language of choice does not support history variables,
demonstrate how this might be implemented.

Solution:
foo_hist = []
trace_var(:$foo){|v| foo_hist.unshift(v)}

$foo = "apple"
$foo = "pear"
$foo = "banana"

p foo_hist # => ["banana", "pear", "apple"]


Hofstadter-Conway $10,000 sequence

The definition of the sequence is colloquially described as:
*   Starting with the list [1,1],
*   Take the last number in the list so far: 1, I'll call it x.
*   Count forward x places from the beginning of the list to find the first number to add (1)
*   Count backward x places from the end of the list to find the second number to add (1)
*   Add the two indexed numbers from the list and the result becomes the next number in the list (1+1)
*   This would then produce [1,1,2] where 2 is the third element of the sequence.

Note that indexing for the description above starts from alternately the left and right ends of the list and starts from an index of ''one''.

A less wordy description of the sequence is:
    a(1)=a(2)=1
    a(n)=a(a(n-1))+a(n-a(n-1))

The sequence begins:
    1, 1, 2, 2, 3, 4, 4, 4, 5, ...

Interesting features of the sequence are that:
*   a(n)/n   tends to   0.5   as   n   grows towards infinity.
*   a(n)/n   where   n   is a power of   2   is   0.5
*   For   n>4   the maximal value of   a(n)/n   between successive powers of 2 decreases.

a(n) / n   for   n   in   1..256

The sequence is so named because John Conway offered a prize of $10,000 to the first person who could
find the first position,   p   in the sequence where
    |a(n)/n| < 0.55  for all  n > p
It was later found that Hofstadter had also done prior work on the sequence.

The 'prize' was won quite quickly by Dr. Colin L. Mallows who proved the properties of the sequence and allowed him to find the value of   n   (which is much smaller than the 3,173,375,556 quoted in the NYT article).

;Task:
#   Create a routine to generate members of the Hofstadter-Conway $10,000 sequence.
#   Use it to show the maxima of   a(n)/n   between successive powers of two up to   2**20
#   As a stretch goal:   compute the value of   n   that would have won the prize and confirm it is true for   n   up to 2**20

;Also see:
*   Conways Challenge Sequence, Mallows' own account.
*   Mathworld Article.

Solution:
class HofstadterConway10000
  def initialize
    @sequence = [nil, 1, 1]
  end

  def [](n)
    raise ArgumentError, "n must be >= 1" if n < 1
    a = @sequence
    a.length.upto(n) {|i| a[i] = a[a[i-1]] + a[i-a[i-1]] }
    a[n]
  end
end

hc = HofstadterConway10000.new

mallows = nil
(1...20).each do |i|
  j = i + 1
  max_n, max_v = -1, -1
  (2**i .. 2**j).each do |n|
    v = hc[n].to_f / n
    max_n, max_v = n, v if v > max_v
    # Mallows number
    mallows = n if v >= 0.55
  end
  puts "maximum between 2^%2d and 2^%2d occurs at%7d: %.8f" % [i, j, max_n, max_v]
end

puts "the mallows number is #{mallows}"


Hofstadter Figure-Figure sequences

These two sequences of positive integers are defined as:
:::: \begin{align}
R(1)&=1\ ;\ S(1)=2 \\
R(n)&=R(n-1)+S(n-1), \quad n>1.
\end{align}

The sequence S(n) is further defined as the sequence of positive integers '''''not''''' present in R(n).

Sequence R starts:
    1, 3, 7, 12, 18, ...
Sequence S starts:
    2, 4, 5, 6, 8, ...

;Task:
# Create two functions named '''ffr''' and '''ffs''' that when given '''n''' return '''R(n)''' or '''S(n)''' respectively.(Note that R(1) = 1 and S(1) = 2 to avoid off-by-one errors).
# No maximum value for '''n''' should be assumed.
# Calculate and show that the first ten values of '''R''' are: 1, 3, 7, 12, 18, 26, 35, 45, 56, and 69
# Calculate and show that the first 40 values of '''ffr''' plus the first 960 values of '''ffs''' include all the integers from 1 to 1000 exactly once.

;References:
* Sloane's A005228 and A030124.
* Wolfram MathWorld
* Wikipedia: Hofstadter Figure-Figure sequences.

Solution:
$r = [nil, 1]
$s = [nil, 2]

def buildSeq(n)
  current = [ $r[-1], $s[-1] ].max
  while $r.length <= n || $s.length <= n
    idx = [ $r.length, $s.length ].min - 1
    current += 1
    if current == $r[idx] + $s[idx]
      $r << current
    else
      $s << current
    end
  end
end

def ffr(n)
  buildSeq(n)
  $r[n]
end

def ffs(n)
  buildSeq(n)
  $s[n]
end

require 'set'
require 'test/unit'

class TestHofstadterFigureFigure < Test::Unit::TestCase
  def test_first_ten_R_values
    r10 = 1.upto(10).map {|n| ffr(n)}
    assert_equal(r10, [1, 3, 7, 12, 18, 26, 35, 45, 56, 69])
  end

  def test_40_R_and_960_S_are_1_to_1000
    rs_values = Set.new
    rs_values.merge( 1.upto(40).collect  {|n| ffr(n)} )
    rs_values.merge( 1.upto(960).collect {|n| ffs(n)} )
    assert_equal(rs_values, Set.new( 1..1000 ))
  end
end


Hofstadter Figure-Figure sequences

Solution:
R = Enumerator.new do |y|
  y << n = 1
  S.each{|s_val| y << n += s_val}
end

S = Enumerator.new do |y|
  y << 2
  y << 4
  u = 5
  R.each do |r_val|
    next if u > r_val
    (u...r_val).each{|r| y << r}
    u = r_val+1
  end
end

p R.take(10)
p S.take(10)
p (R.take(40)+ S.take(960)).sort == (1..1000).to_a


Hofstadter Q sequence

The Hofstadter Q sequence is defined as:
:: \begin{align}
Q(1)&=Q(2)=1, \\
Q(n)&=Q\big(n-Q(n-1)\big)+Q\big(n-Q(n-2)\big), \quad n>2.
\end{align}

It is defined like the [[Fibonacci sequence]], but whereas the next term in the Fibonacci sequence is the sum of the previous two terms, in the Q sequence the previous two terms tell you how far to go back in the Q sequence to find the two numbers to sum to make the next term of the sequence.

;Task:
* Confirm and display that the first ten terms of the sequence are: 1, 1, 2, 3, 3, 4, 5, 5, 6, and 6
* Confirm and display that the 1000th term is:   502

;Optional extra credit
* Count and display how many times a member of the sequence is less than its preceding term for terms up to and including the 100,000th term.
* Ensure that the extra credit solution   ''safely''   handles being initially asked for an '''n'''th term where   '''n'''   is large.
(This point is to ensure that caching and/or recursion limits, if it is a concern, is correctly handled).

Solution:
@cache = []
def Q(n)
  if @cache[n].nil?
    case n
    when 1, 2 then @cache[n] = 1
    else @cache[n] = Q(n - Q(n-1)) + Q(n - Q(n-2))
    end
  end
  @cache[n]
end

puts "first 10 numbers in the sequence: #{(1..10).map {|n| Q(n)}}"
puts "1000'th term: #{Q(1000)}"

prev = Q(1)
count = 0
2.upto(100_000) do |n|
  q = Q(n)
  count += 1 if q < prev
  prev = q
end
puts "number of times in the first 100,000 terms where Q(i)<Q(i-1): #{count}"


Horner's rule for polynomial evaluation

A fast scheme for evaluating a polynomial such as:
: -19+7x-4x^2+6x^3\,
when
: x=3\;.
is to arrange the computation as follows:
: ((((0) x + 6) x + (-4)) x + 7) x + (-19)\;
And compute the result from the innermost brackets outwards as in this pseudocode:
 coefficients ''':=''' [-19, 7, -4, 6] ''# list coefficients of all x^0..x^n in order''
 x ''':=''' 3
 accumulator ''':=''' 0
 '''for''' i '''in''' ''length''(coefficients) '''downto''' 1 '''do'''
     ''# Assumes 1-based indexing for arrays''
     accumulator ''':=''' ( accumulator * x ) + coefficients[i]
 '''done'''
 ''# accumulator now has the answer''

'''Task Description'''
:Create a routine that takes a list of coefficients of a polynomial in order of increasing powers of x; together with a value of x to compute its value at, and return the value of the polynomial at that value using Horner's rule.

Cf. [[Formal power series]]

Solution:
def horner(coeffs, x)
  coeffs.reverse.inject(0) {|acc, coeff| acc * x + coeff}
end
p horner([-19, 7, -4, 6], 3)  # ==> 128


ISBN13 check digit

Validate the check digit of an ISBN-13 code:
::*   Multiply every other digit by  '''3'''.
::*   Add these numbers and the other digits.
::*   Take the remainder of this number after division by  '''10'''.
::*   If it is  '''0''',   the ISBN-13 check digit is correct.

You might use the following codes for testing:
::::*   978-0596528126              (good)
::::*   978-0596528120          (bad)
::::*   978-1788399081              (good)
::::*   978-1788399083          (bad)

Show output here, on this page

;See also:
:*   for details:   13-digit ISBN method of validation.       (installs cookies.)

Solution:
def validISBN13?(str)
  cleaned = str.delete("^0-9").chars
  return false unless cleaned.size == 13
  cleaned.each_slice(2).sum{|d1, d2| d1.to_i + 3*d2.to_i }.remainder(10) == 0
end

isbns = ["978-1734314502", "978-1734314509", "978-1788399081", "978-1788399083"]
isbns.each{|isbn| puts "#{isbn}: #{validISBN13?(isbn)}" }


I before E except after C

The phrase      "I before E, except after C"     is a
widely known mnemonic which is supposed to help when spelling English words.

;Task:
Using the word list from   http://wiki.puzzlers.org/pub/wordlists/unixdict.txt,
check if the two sub-clauses of the phrase are plausible individually:
:::#   ''"I before E when not preceded by C"''
:::#   ''"E before I when preceded by C"''

If both sub-phrases are plausible then the original phrase can be said to be plausible.

Something is plausible if the number of words having the feature is more than two times the number of words having the opposite feature (where feature is 'ie' or 'ei' preceded or not by 'c' as appropriate).

;Stretch goal:
As a stretch goal use the entries from the table of Word Frequencies in Written and Spoken English: based on the British National Corpus, (selecting those rows with three space or tab separated words only), to see if the phrase is plausible when word frequencies are taken into account.

''Show your output here as well as your program.''

;cf.:
* Schools to rethink 'i before e' - BBC news, 20 June 2009
* I Before E Except After C - QI Series 8 Ep 14, (humorous)
* Companion website for the book: "Word Frequencies in Written and Spoken English: based on the British National Corpus".

Solution:
require 'open-uri'

plausibility_ratio = 2
counter = Hash.new(0)
path = 'http://wiki.puzzlers.org/pub/wordlists/unixdict.txt'
rules = [['I before E when not preceded by C:', 'ie', 'ei'],
         ['E before I when preceded by C:', 'cei', 'cie']]

open(path){|f| f.each{|line| line.scan(/ie|ei|cie|cei/){|match| counter[match] += 1 }}}

overall_plausible = rules.all? do |(str, x, y)|
  num_x, num_y, ratio = counter[x], counter[y], counter[x] / counter[y].to_f
  plausibility = ratio > plausibility_ratio
  puts str
  puts "#{x}: #{num_x}; #{y}: #{num_y}; Ratio: #{ratio.round(2)}: #{ plausibility ? 'Plausible' : 'Implausible'}"
  plausibility
end

puts "Overall: #{overall_plausible ? 'Plausible' : 'Implausible'}."


Identity matrix

Build an   identity matrix   of a size known at run-time.

An ''identity matrix'' is a square matrix of size '''''n'' x ''n''''',
where the diagonal elements are all '''1'''s (ones),
and all the other elements are all '''0'''s (zeroes).

I_n = \begin{bmatrix}
  1      & 0      & 0      & \cdots & 0      \\
  0      & 1      & 0      & \cdots & 0      \\
  0      & 0      & 1      & \cdots & 0      \\
  \vdots & \vdots & \vdots & \ddots & \vdots \\
  0      & 0      & 0      & \cdots & 1      \\
\end{bmatrix}

;Related tasks:
*   [[Spiral matrix]]
*   [[Zig-zag matrix]]
*   [[Ulam_spiral_(for_primes)]]

Solution:
def identity(size)
  Array.new(size){|i| Array.new(size){|j| i==j ? 1 : 0}}
end

[4,5,6].each do |size|
  puts size, identity(size).map {|r| r.to_s}, ""
end


Idiomatically determine all the lowercase and uppercase letters   (of the Latin [English] alphabet)   being used currently by a computer programming language.
The method should find the letters regardless of the hardware architecture that is being used (ASCII, EBCDIC, or other).

;Task requirements

Display the set of all:
::::::*   lowercase letters
::::::*   uppercase letters

that can be used (allowed) by the computer program,

where   ''letter''   is a member of the Latin (English) alphabet:     '''a''' --> '''z'''     and     '''A''' --> '''Z'''.

You may want to mention what hardware architecture is being used, and if applicable, the operating system.

;See also
* Idiomatically determine all the characters that can be used for symbols.

Solution: puts "Lowercase:", [*"a".."z"].join, "Uppercase:", [*"A".."Z"].join


Imaginary base numbers

Imaginary base numbers are a non-standard positional numeral system which uses an imaginary number as its radix. The most common is quater-imaginary with radix 2i.

''The quater-imaginary numeral system was first proposed by Donald Knuth in 1955 as a submission for a high school science talent search.  [Ref.]''

Other imaginary bases are possible too but are not as widely discussed and aren't specifically named.

'''Task:''' Write a set of procedures (functions, subroutines, however they are referred to in your language) to convert base 10 numbers to an imaginary base and back.

At a minimum, support quater-imaginary (base 2i).

For extra kudos, support positive or negative bases 2i through 6i (or higher).

As a stretch goal, support converting non-integer numbers ( E.G. 227.65625+10.859375i ) to an imaginary base.

See Wikipedia: Quater-imaginary_base for more details.

For reference, here are some some decimal and complex numbers converted to quater-imaginary.

Base 10
Base 2i

1
 1

2
 2

3
 3

4
 10300

5
 10301

6
 10302

7
 10303

8
 10200

9
 10201

10
 10202

11
 10203

12
 10100

13
 10101

14
 10102

15
 10103

16
 10000

Base 10
Base 2i

-1
 103

-2
 102

-3
 101

-4
 100

-5
 203

-6
 202

-7
 201

-8
 200

-9
 303

-10
 302

-11
 301

-12
 300

-13
 1030003

-14
 1030002

-15
 1030001

-16
 1030000

Base 10
Base 2i

1i
10.2

2i
10.0

3i
20.2

4i
20.0

5i
30.2

6i
30.0

7i
103000.2

8i
103000.0

9i
103010.2

10i
103010.0

11i
103020.2

12i
103020.0

13i
103030.2

14i
103030.0

15i
102000.2

16i
102000.0

Base 10
Base 2i

-1i
0.2

-2i
1030.0

-3i
1030.2

-4i
1020.0

-5i
1020.2

-6i
1010.0

-7i
1010.2

-8i
1000.0

-9i
1000.2

-10i
2030.0

-11i
2030.2

-12i
2020.0

-13i
2020.2

-14i
2010.0

-15i
2010.2

-16i
2000.0

Solution:
# Extend class Integer with a string conveter.

class Integer
  def as_str()
    return to_s()
  end
end

# Extend class Complex with a string conveter (works only with Gaussian integers).

class Complex
  def as_str()
    return '0' if self == 0
    return real.to_i.to_s if imag == 0
    return imag.to_i.to_s + 'i' if real == 0
    return real.to_i.to_s + '+' + imag.to_i.to_s + 'i' if imag >= 0
    return real.to_i.to_s + '-' + (-(imag.to_i)).to_s + 'i'
  end
end

# Emit various tables of conversions.

1.step(16) do |gi|
  puts(" %4s -> %8s -> %4s     %4s -> %8s -> %4s" %
    [gi.as_str, base2i_encode(gi), base2i_decode(base2i_encode(gi)).as_str,
     (-gi).as_str, base2i_encode(-gi), base2i_decode(base2i_encode(-gi)).as_str])
end
puts
1.step(16) do |gi|
  gi *= 0+1i
  puts(" %4s -> %8s -> %4s     %4s -> %8s -> %4s" %
    [gi.as_str, base2i_encode(gi), base2i_decode(base2i_encode(gi)).as_str,
     (-gi).as_str, base2i_encode(-gi), base2i_decode(base2i_encode(-gi)).as_str])
end
puts
0.step(3) do |m|
  0.step(3) do |l|
    0.step(3) do |h|
      qi = (100 * h + 10 * m + l).to_s
      gi = base2i_decode(qi)
      md = base2i_encode(gi).match(/^(?<num>[0-3]+)(?:\.0)?$/)
      print(" %4s -> %6s -> %4s" % [qi, gi.as_str, md[:num]])
    end
    puts
  end
end


Increasing gaps between consecutive Niven numbers

Note:   '''Niven'''   numbers are also called   '''Harshad'''        numbers.
::::   They are also called                     '''multidigital'''   numbers.

'''Niven''' numbers are positive integers which are evenly divisible by the sum of its
digits   (expressed in base ten).

''Evenly divisible''   means   ''divisible with no remainder''.

;Task:
:*   find the gap (difference) of a Niven number from the previous Niven number
:*   if the gap is   ''larger''   than the (highest) previous gap,   then:
:::*   show the index (occurrence) of the gap      (the 1st gap is   '''1''')
:::*   show the index of the Niven number that starts the gap     (1st Niven number is   '''1''',   33rd Niven number is   '''100''')
:::*   show the Niven number that starts the gap
:::*   show all numbers with comma separators where appropriate   (optional)
:::*   I.E.:   the gap size of   '''60'''   starts at the   33,494th   Niven number which is Niven number   '''297,864'''
:*   show all increasing gaps up to the   ten millionth   ('''10,000,000th''')   Niven number
:*   (optional)   show all gaps up to whatever limit is feasible/practical/realistic/reasonable/sensible/viable on your computer
:*   show all output here, on this page

;Related task:
:*   Harshad or Niven series.

;Also see:
:*   Journal of Integer Sequences, Vol. 6 (2004), Article 03.2.5, Large and Small Gaps Between Consecutive Niven Numbers.
:*   (PDF) version of the (above) article by Doyon.

Solution:
nivens = Enumerator.new {|y| (1..).each {|n| y << n if n.remainder(n.digits.sum).zero?} }

cur_gap = 0
puts 'Gap    Index of gap  Starting Niven'

nivens.each_cons(2).with_index(1) do |(n1, n2), i|
  break if i > 10_000_000
  if n2-n1 > cur_gap then
    printf "%3d %15s %15s\n", n2-n1, i, n1
    cur_gap = n2-n1
  end
end


Index finite lists of positive integers

It is known that the set of finite lists of positive integers is    countable.

This means that there exists a subset of natural integers which can be mapped to the set of finite lists of positive integers.

;Task:
Implement such a mapping:
:*   write a function     ''rank''     which assigns an integer to any finite, arbitrarily long list of arbitrary large positive integers.
:*   write a function          ''unrank''        which is the   ''rank''    inverse function.

Demonstrate your solution by:
:*   picking a random-length list of random positive integers
:*   turn it into an integer,   and
:*   get the list back.

There are many ways to do this.   Feel free to choose any one you like.

;Extra credit:
Make the   ''rank''   function as a    bijection   and show   ''unrank(n)''   for   '''n'''   varying from   '''0'''   to   '''10'''.

Solution:
def unrank(n)
  return [0] if n==1
  n.to_s(2)[1..-1].split('0',-1).map(&:size)
end

def rank(x)
  return 0 if x.empty?
  ('1' + x.map{ |a| '1'*a }.join('0')).to_i(2)
end

for x in 0..10
  puts "%3d : %-18s: %d" % [x, a=unrank(x), rank(a)]
end

puts
x = [1, 2, 3, 5, 8]
puts "#{x} => #{rank(x)} => #{unrank(rank(x))}"


Integer overflow

Some languages support one or more integer types of the underlying processor.

This integer types have fixed size;   usually   '''8'''-bit,   '''16'''-bit,   '''32'''-bit,   or   '''64'''-bit.
The integers supported by such a type can be   ''signed''   or   ''unsigned''.

Arithmetic for machine level integers can often be done by single CPU instructions.
This allows high performance and is the main reason to support machine level integers.

;Definition:
An integer overflow happens when the result of a computation does not fit into the fixed size integer.
The result can be too small or too big to be representable in the fixed size integer.

;Task:
When a language has fixed size integer types, create a program that
does arithmetic computations for the fixed size integers of the language.

These computations must be done such that the result would overflow.

The program should demonstrate what the following expressions do.

For 32-bit signed integers:
::::: {|class="wikitable"
!Expression
!Result that does not fit into a 32-bit signed integer
|-
| -(-2147483647-1)
| 2147483648
|-
| 2000000000 + 2000000000
| 4000000000
|-
| -2147483647 - 2147483647
| -4294967294
|-
| 46341 * 46341
| 2147488281
|-
| (-2147483647-1) / -1
| 2147483648
|}

For 64-bit signed integers:
::: {|class="wikitable"
!Expression
!Result that does not fit into a 64-bit signed integer
|-
| -(-9223372036854775807-1)
| 9223372036854775808
|-
| 5000000000000000000+5000000000000000000
| 10000000000000000000
|-
| -9223372036854775807 - 9223372036854775807
| -18446744073709551614
|-
| 3037000500 * 3037000500
| 9223372037000250000
|-
| (-9223372036854775807-1) / -1
| 9223372036854775808
|}

For 32-bit unsigned integers:
::::: {|class="wikitable"
!Expression
!Result that does not fit into a 32-bit unsigned integer
|-
| -4294967295
| -4294967295
|-
| 3000000000 + 3000000000
| 6000000000
|-
| 2147483647 - 4294967295
| -2147483648
|-
| 65537 * 65537
| 4295098369
|}

For 64-bit unsigned integers:
::: {|class="wikitable"
!Expression
!Result that does not fit into a 64-bit unsigned integer
|-
| -18446744073709551615
| -18446744073709551615
|-
| 10000000000000000000 + 10000000000000000000
| 20000000000000000000
|-
| 9223372036854775807 - 18446744073709551615
| -9223372036854775808
|-
| 4294967296 * 4294967296
| 18446744073709551616
|}

;Notes:
:*   When the integer overflow does trigger an exception show how the exception is caught.
:*   When the integer overflow produces some value,   print it.
:*   It should be explicitly noted when an integer overflow is not recognized,   the program continues with wrong results.
:*   This should be done for signed and unsigned integers of various sizes supported by the computer programming language.
:*   When a language has no fixed size integer type,   or when no integer overflow can occur for other reasons,   this should be noted.
:*   It is okay to mention,   when a language supports unlimited precision integers,   but this task is NOT the place to demonstrate the   capabilities of unlimited precision integers.

Solution:
2.1.1 :001 > a = 2**62 -1
 => 4611686018427387903
2.1.1 :002 > a.class
 => Fixnum
2.1.1 :003 > (b = a + 1).class
 => Bignum
2.1.1 :004 > (b-1).class
 => Fixnum


Intersecting number wheels

A number wheel has:
* A ''name'' which is an uppercase letter.
* A set of ordered ''values'' which are either ''numbers'' or ''names''.

A ''number'' is generated/yielded from a named wheel by:
:1. Starting at the first value of the named wheel and advancing through subsequent values and wrapping around to the first value to form a "wheel":
::1.a If the value is a number, yield it.
::1.b If the value is a name, yield the next value from the named wheel
::1.c Advance the position of this wheel.

Given the wheel
: A: 1 2 3
the number 1 is first generated, then 2, then 3, 1, 2, 3, 1, ...

'''Note:''' When more than one wheel is defined as a set of intersecting wheels then the
first named wheel is assumed to be the one that values are generated from.

;Examples:
Given the wheels:
    A: 1 B 2
    B: 3 4
The series of numbers generated starts:
    1, 3, 2, 1, 4, 2, 1, 3, 2, 1, 4, 2, 1, 3, 2...

The intersections of number wheels can be more complex, (and might loop forever),
and wheels may be multiply connected.

'''Note:''' If a named wheel is referenced more than
once by one or many other wheels, then there is only one position of the wheel
that is advanced by each and all references to it.

E.g.
  A:  1 D D
  D:  6 7 8
  Generates:
    1 6 7 1 8 6 1 7 8 1 6 7 1 8 6 1 7 8 1 6 ...

;Task:
Generate and show the first twenty terms of the sequence of numbers generated
from these groups:

    Intersecting Number Wheel group:
      A:  1 2 3

    Intersecting Number Wheel group:
      A:  1 B 2
      B:  3 4

    Intersecting Number Wheel group:
      A:  1 D D
      D:  6 7 8

    Intersecting Number Wheel group:
      A:  1 B C
      B:  3 4
      C:  5 B

Show your output here, on this page.

Solution:
groups = [{A: [1, 2, 3]},
          {A: [1, :B, 2], B: [3, 4]},
          {A: [1, :D, :D], D: [6, 7, 8]},
          {A: [1, :B, :C], B: [3, 4], C: [5, :B]} ]

groups.each do |group|
  p group
  wheels = group.transform_values(&:cycle)
  res = 20.times.map do
    el = wheels[:A].next
    el = wheels[el].next until el.is_a?(Integer)
    el
  end
  puts res.join(" "),""
end


Inverted syntax

'''Inverted syntax with conditional expressions'''

In traditional syntax conditional expressions are usually shown before the action within a statement or code block:

 IF raining=true THEN needumbrella=true

In inverted syntax, the action is listed before the conditional expression in the statement or code block:

 needumbrella=true IF raining=true

'''Inverted syntax with assignment'''

In traditional syntax, assignments are usually expressed with the variable appearing before the expression:

 a = 6

In inverted syntax, the expression appears before the variable:
 6 = a

'''Task'''

The task is to demonstrate support for inverted syntax forms within the language by showing both the traditional and inverted forms.

Solution:
# Raise ArgumentError if n is negative.
if n < 0 then raise ArgumentError, "negative n" end
raise ArgumentError, "negative n" if n < 0

# Exit 1 unless we can call Process.fork.
unless Process.respond_to? :fork then exit 1 end
exit 1 unless Process.respond_to? :fork

# Empty an array, printing each element.
while ary.length > 0 do puts ary.shift end
puts ary.shift while ary.length > 0

# Another way to empty an array, printing each element.
until ary.empty? do puts ary.shift end
puts ary.shift until ary.empty?


Isograms and heterograms

Definitions
For the purposes of this task, an '''isogram''' means a string where each character present is used the same number of times and an '''n-isogram''' means an isogram where each character present is used exactly '''n''' times.

A '''heterogram''' means a string in which no character occurs more than once. It follows that a '''heterogram''' is the same thing as a '''1-isogram'''.

;Examples
''caucasus'' is a '''2-isogram''' because the letters c, a, u and s all occur twice.

''atmospheric'' is a '''heterogram''' because all its letters are used once only.

;Task
Using '''unixdict.txt''' and ignoring capitalization:

'''1)''' Find and display here all words which are '''n-isograms''' where '''n > 1'''.

Present the results as a single list but sorted as follows:

a. By decreasing order of '''n''';

b. Then by decreasing order of word length;

c. Then by ascending lexicographic order.

'''2)''' Secondly, find and display here all words which are '''heterograms''' and have more than '''10''' characters.

Again present the results as a single list but sorted as per b. and c. above.

;Reference

* Wikipedia: Heterogram

Solution:
words = File.readlines("unixdict.txt", chomp: true)

isograms = words.group_by do |word|
  char_counts = word.downcase.chars.tally.values
  char_counts.first if char_counts.uniq.size == 1
end
isograms.delete(nil)
isograms.transform_values!{|ar| ar.sort_by{|word| [-word.size, word]} }

keys = isograms.keys.sort.reverse
keys.each{|k| puts "(#{isograms[k].size}) #{k}-isograms: #{isograms[k]} " if k > 1 }

min_chars = 10
large_heterograms = isograms[1].select{|word| word.size > min_chars }
puts "" , "(#{large_heterograms.size}) heterograms with more than #{min_chars} chars:"
puts large_heterograms


Isqrt (integer square root) of X

Sometimes a function is needed to find the integer square root of   '''X''',   where   '''X'''   can be a
real non-negative number.

Often   '''X'''   is actually a non-negative integer.

For the purposes of this task,   '''X'''   can be an integer or a real number,   but if it
simplifies things in your computer programming language,   assume it's an integer.

One of the most common uses of   '''Isqrt'''   is in the division of an integer by all factors   (or
primes)   up to the
 X     of that
integer,   either to find the factors of that integer,   or to determine primality.

An alternative method for finding the   '''Isqrt'''   of a number is to
calculate:        floor( sqrt(X) )
::*   where    '''sqrt'''    is the   square root   function for non-negative real numbers,   and
::*   where   '''floor'''         is the   floor         function for real numbers.

If the hardware supports the computation of (real) square roots,   the above method might be a faster method for
small numbers that don't have very many significant (decimal) digits.

However, floating point arithmetic is limited in the number of   (binary or decimal)   digits that it can support.

;Pseudo-code using quadratic residue:
For this task, the integer square root of a non-negative number will be computed using a version
of   ''quadratic residue'',   which has the advantage that no   ''floating point''   calculations are
used,   only integer arithmetic.

Furthermore, the two divisions can be performed by bit shifting,   and the one multiplication can also be be performed by bit shifting or additions.

The disadvantage is the limitation of the size of the largest integer that a particular computer programming language can support.

Pseudo-code of a procedure for finding the integer square root of   '''X'''       (all variables are integers):
          q <-- 1                                /*initialize  Q  to unity.  */
                                   /*find a power of 4 that's greater than X.*/
                   perform  while q <= x         /*perform while  Q <= X.    */
                   q <-- q * 4                   /*multiply  Q  by  four.    */
                   end  /*perform*/
                                                 /*Q  is now greater than  X.*/
          z <-- x                                /*set  Z  to the value of X.*/
          r <-- 0                                /*initialize  R  to zero.   */
                   perform  while q > 1          /*perform while  Q > unity. */
                   q <-- q / 4                   /*integer divide by  four.  */
                   t <-- z - r - q               /*compute value of  T.      */
                   r <-- r / 2                   /*integer divide by  two.   */
                   if t >= 0  then do
                                   z <-- t       /*set  Z  to value of  T.   */
                                   r <-- r + q   /*compute new value of  R.  */
                                   end
                   end  /*perform*/
                                                 /*R  is now the  Isqrt(X).  */

          /* Sidenote: Also, Z is now the remainder after square root (i.e.  */
          /*           R^2 + Z = X, so if Z = 0 then X is a perfect square). */

Another version for the (above)   1st   '''perform'''   is:
                   perform  until q > X          /*perform until  Q > X.     */
                   q <-- q * 4                   /*multiply  Q  by  four.    */
                   end  /*perform*/

Integer square roots of some values:
 Isqrt( 0)  is   0               Isqrt(60)  is  7                Isqrt( 99)  is   9
 Isqrt( 1)  is   1               Isqrt(61)  is  7                Isqrt(100)  is  10
 Isqrt( 2)  is   1               Isqrt(62)  is  7                Isqrt(102)  is  10
 Isqrt( 3)  is   1               Isqrt(63)  is  7
 Isqrt( 4)  is   2               Isqrt(64)  is  8                Isqet(120)  is  10
 Isqrt( 5)  is   2               Isqrt(65)  is  8                Isqrt(121)  is  11
 Isqrt( 6)  is   2               Isqrt(66)  is  8                Isqrt(122)  is  11
 Isqrt( 7)  is   2               Isqrt(67)  is  8
 Isqrt( 8)  is   2               Isqrt(68)  is  8                Isqrt(143)  is  11
 Isqrt( 9)  is   3               Isqrt(69)  is  8                Isqrt(144)  is  12
 Isqrt(10)  is   3               Isqrt(70)  is  8                Isqrt(145)  is  12

;Task:
Compute and show all output here   (on this page)   for:
::*   the Isqrt of the     integers     from     '''0''' ---> '''65'''                (inclusive), shown in a       horizontal       format.
::*   the Isqrt of the   odd powers               from          '''71''' ---> '''773'''   (inclusive), shown in a   vertical   format.
::*   use commas in the displaying of larger numbers.

You can show more numbers for the 2nd requirement if the displays fits on one screen on Rosetta Code.
If your computer programming language only supports smaller integers,   show what you can.

;Related tasks:
:*   sequence of non-squares
:*   integer roots
:*   square root by hand

Solution:
module Commatize
  refine Integer do
    def commatize
      self.to_s.gsub( /(\d)(?=\d{3}+(?:\.|$))(\d{3}\..*)?/, "\\1,\\2")
    end
  end
end

using Commatize
def isqrt(x)
    q, r = 1, 0
    while (q <= x) do q <<= 2 end
    while (q > 1) do
        q >>= 2; t = x-r-q; r >>= 1
        if (t >= 0) then x, r = t, r+q end
    end
    r
end

puts (0..65).map{|n| isqrt(n) }.join(" ")

1.step(73, 2) do |n|
  print "#{n}:\t"
  puts isqrt(7**n).commatize
end


Iterated digits squaring

If you add the square of the digits of a Natural number (an integer bigger than zero), you always end with either 1 or 89:
15 -> 26 -> 40 -> 16 -> 37 -> 58 -> 89
7 -> 49 -> 97 -> 130 -> 10 -> 1

An example in Python:

>>> step = lambda x: sum(int(d) ** 2 for d in str(x))
>>> iterate = lambda x: x if x in [1, 89] else iterate(step(x))
>>> [iterate(x) for x in xrange(1, 20)]
[1, 89, 89, 89, 89, 89, 1, 89, 89, 1, 89, 89, 1, 89, 89, 89, 89, 89, 1]

;Task:
: Count how many number chains for integers 1 <= n < 100_000_000 end with a value 89.
Or, for much less credit - (showing that your algorithm and/or language is slow):
: Count how many number chains for integers 1 <= n < 1_000_000 end with a value 89.

This problem derives from the Project Euler problem 92.

For a quick algorithm for this task see the talk page

;Related tasks:
* [[Combinations with repetitions]]
* [[Digital root]]
* [[Digital root/Multiplicative digital root]]

Solution:
# Count how many number chains for Natural Numbers < 10**d end with a value of 1.
def iterated_square_digit(d)
  f = Array.new(d+1){|n| (1..n).inject(1, :*)}      #Some small factorials
  g = -> (n) { res = n.digits.sum{|d| d*d}
               res==89 ? 0 : res }

  #An array: table[n]==0 means that n translates to 89 and 1 means that n translates to 1
  table = Array.new(d*81+1){|n| n.zero? ? 1 : (i=g.call(n))==89 ? 0 : i}
  table.collect!{|n| n = table[n] while n>1; n}
  z = 0                                             #Running count of numbers translating to 1
  [*0..9].repeated_combination(d) do |rc|           #Iterate over unique digit combinations
    next if table[rc.inject(0){|g,n| g+n*n}].zero?  #Count only ones
    nn = [0] * 10                                   #Determine how many numbers this digit combination corresponds to
    rc.each{|n| nn[n] += 1}
    z += nn.inject(f[d]){|gn,n| gn / f[n]}          #Add to the count of numbers terminating in 1
  end
  puts "\nd=(#{d}) in the range 1 to #{10**d-1}",
       "#{z} numbers produce 1 and #{10**d-1-z} numbers produce 89"
end

[8, 11, 14, 17].each do |d|
  t0 = Time.now
  iterated_square_digit(d)
  puts "  #{Time.now - t0} sec"
end


JSON

Load a JSON string into a data structure.
Also, create a new data structure and serialize it into JSON.

Use objects and arrays (as appropriate for your language)
and make sure your JSON is valid (https://jsonformatter.org).

Solution:
require 'json'

ruby_obj = JSON.parse('{"blue": [1, 2], "ocean": "water"}')
puts ruby_obj

ruby_obj["ocean"] = { "water" => ["fishy", "salty"] }
puts JSON.generate(ruby_obj)
puts JSON.pretty_generate(ruby_obj)


Jacobi symbol

The '''Jacobi symbol''' is a multiplicative function that generalizes the Legendre symbol. Specifically, the Jacobi symbol (a | n) equals the product of the Legendre symbols (a | p_i)^(k_i), where n = p_1^(k_1)*p_2^(k_2)*...*p_i^(k_i) and the Legendre symbol (a | p) denotes the value of  a ^ ((p-1)/2) (mod p)
* (a | p)     1      if a is a square (mod p)
* (a | p)         -1      if a is not a square (mod p)
* (a | p)     0      if a  0

If n is prime, then the Jacobi symbol (a | n) equals the Legendre symbol (a | n).

;Task:
Calculate the Jacobi symbol (a | n).

;Reference:
* Wikipedia article on Jacobi symbol.

Solution:
def jacobi(a, n)
  raise ArgumentError.new "n must b positive and odd" if n < 1 || n.even?
  res = 1
  until (a %= n) == 0
    while a.even?
      a >>= 1
      res = -res if [3, 5].include? n % 8
    end
    a, n = n, a
    res = -res if [a % 4, n % 4] == [3, 3]
  end
  n == 1 ? res : 0
end

puts "Jacobian symbols for jacobi(a, n)"
puts "n\\a  0  1  2  3  4  5  6  7  8  9 10"
puts "------------------------------------"
1.step(to: 17, by: 2) do |n|
   printf("%2d ", n)
   (0..10).each { |a| printf(" % 2d", jacobi(a, n)) }
   puts
end


Jacobsthal numbers

'''Jacobsthal numbers''' are an integer sequence related to Fibonacci numbers. Similar to Fibonacci, where each term is the sum of the previous two terms, each term is the sum of the previous, plus twice the one before that. Traditionally the sequence starts with the given terms 0, 1.

    J0 = 0
    J1 = 1
    Jn = Jn-1 + 2 x Jn-2

Terms may be calculated directly using one of several possible formulas:

    Jn = ( 2n - (-1)n ) / 3

'''Jacobsthal-Lucas numbers''' are very similar. They have the same recurrence relationship, the only difference is an initial starting value '''J0 = 2''' rather than '''J0 = 0'''.

Terms may be calculated directly using one of several possible formulas:

    JLn = 2n + (-1)n

'''Jacobsthal oblong numbers''' is the sequence obtained from multiplying each '''Jacobsthal number''' '''Jn''' by its direct successor '''Jn+1'''.

'''Jacobsthal primes''' are '''Jacobsthal numbers''' that are prime.

;Task
* Find and display the first 30 '''Jacobsthal numbers'''
* Find and display the first 30 '''Jacobsthal-Lucas numbers'''
* Find and display the first 20 '''Jacobsthal oblong numbers'''
* Find and display at least the first 10 '''Jacobsthal primes'''

;See also
;* Wikipedia: Jacobsthal number
;* Numbers Aplenty - Jacobsthal number
;* OEIS:A001045 - Jacobsthal sequence (or Jacobsthal numbers)
;* OEIS:A014551 - Jacobsthal-Lucas numbers.
;* OEIS:A084175 - Jacobsthal oblong numbers
;* OEIS:A049883 - Primes in the Jacobsthal sequence
;* Related task: Fibonacci sequence
;* Related task: Leonardo numbers

Solution:
require 'prime'

def jacobsthal(n) = (2**n + n[0])/3
def jacobsthal_lucas(n) = 2**n + (-1)**n
def jacobsthal_oblong(n) = jacobsthal(n) * jacobsthal(n+1)

puts "First 30 Jacobsthal numbers:"
puts (0..29).map{|n| jacobsthal(n) }.join(" ")

puts "\nFirst 30 Jacobsthal-Lucas numbers: "
puts (0..29).map{|n| jacobsthal_lucas(n) }.join(" ")

puts "\nFirst 20 Jacobsthal-Oblong numbers: "
puts (0..19).map{|n| jacobsthal_oblong(n) }.join(" ")

puts "\nFirst 10 prime Jacobsthal numbers: "
res = (0..).lazy.filter_map do |i|
  j = jacobsthal(i)
  j if j.prime?
end
puts res.take(10).force.join(" ")


Jaro similarity

The Jaro distance is a measure of edit distance between two strings; its inverse, called the ''Jaro similarity'', is a measure of two strings' similarity: the higher the value, the more similar the strings are. The score is normalized such that   '''0'''   equates to no similarities and   '''1'''   is an exact match.

;;Definition

The Jaro similarity   d_j   of two given strings   s_1   and   s_2   is

: d_j = \left\{

\begin{array}{l l}
  0 & \text{if }m = 0\\
  \frac{1}{3}\left(\frac{m}{|s_1|} + \frac{m}{|s_2|} + \frac{m-t}{m}\right) & \text{otherwise} \end{array} \right.

Where:

* m   is the number of ''matching characters'';
* t   is half the number of ''transpositions''.

Two characters from   s_1   and   s_2   respectively, are considered ''matching'' only if they are the same and not farther apart than   \left\lfloor\frac{\max(|s_1|,|s_2|)}{2}\right\rfloor-1 characters.

Each character of   s_1   is compared with all its matching characters in   s_2. Each difference in position is half a ''transposition''; that is, the number of transpositions is half the number of characters which are common to the two strings but occupy different positions in each one.

;;Example

Given the strings   s_1   ''DWAYNE''   and   s_2   ''DUANE''   we find:

* m = 4
* |s_1| = 6
* |s_2| = 5
* t = 0

We find a Jaro score of:

: d_j = \frac{1}{3}\left(\frac{4}{6} + \frac{4}{5} + \frac{4-0}{4}\right) = 0.822

;Task

Implement the Jaro algorithm and show the similarity scores for each of the following pairs:

* ("MARTHA", "MARHTA")
* ("DIXON", "DICKSONX")
* ("JELLYFISH", "SMELLYFISH")

; See also
* Jaro-Winkler distance on Wikipedia.

Solution:
def jaro(s, t)
    return 1.0 if s == t

    s_len = s.size
    t_len = t.size
    match_distance = ([s_len, t_len].max / 2) - 1

    s_matches = []
    t_matches = []
    matches = 0.0

    s_len.times do |i|
        j_start = [0, i-match_distance].max
        j_end = [i+match_distance, t_len-1].min

        (j_start..j_end).each do |j|
            t_matches[j] && next
            s[i] == t[j] || next
            s_matches[i] = true
            t_matches[j] = true
            matches += 1.0
            break
        end
    end

    return 0.0 if matches == 0.0

    k = 0
    transpositions = 0.0
    s_len.times do |i|
        s_matches[i] || next
        k += 1 until t_matches[k]
        s[i] == t[k] || (transpositions += 1.0)
        k += 1
    end

    ((matches / s_len) +
     (matches / t_len) +
     ((matches - transpositions/2.0) / matches)) / 3.0
end

%w(
    MARTHA    MARHTA
    DIXON     DICKSONX
    JELLYFISH SMELLYFISH
).each_slice(2) do |s,t|
    puts "jaro(#{s.inspect}, #{t.inspect}) = #{'%.10f' % jaro(s, t)}"
end


Jewels and stones

Create a function which takes two string parameters: 'stones' and 'jewels' and returns an integer.

Both strings can contain any number of upper or lower case letters. However, in the case of 'jewels', all letters must be distinct.

The function should count (and return) how many 'stones' are 'jewels' or, in other words, how many letters in 'stones' are also letters in 'jewels'.

Note that:
:# Only letters in the ISO basic Latin alphabet i.e. 'A to Z' or 'a to z' need be considered.
:# A lower case letter is considered to be different from its upper case equivalent for this purpose, i.e., 'a' != 'A'.
:# The parameters do not need to have exactly the same names.
:# Validating the arguments is unnecessary.

So, for example, if passed "aAAbbbb" for 'stones' and "aA" for 'jewels', the function should return 3.

This task was inspired by this problem.

Solution:
stones, jewels = "aAAbbbb", "aA"

stones.count(jewels)  # => 3


Juggler sequence

Background of the   '''juggler sequence''':

Juggler sequences were publicized by an American mathematician and author   Clifford A. Pickover.   The name of the sequence gets it's name from the similarity of the rising and falling nature of the numbers in the sequences,   much like balls in the hands of a juggler.

;Description
A juggler sequence is an integer sequence that starts with a positive integer a[0], with each subsequent term in the sequence being defined by the recurrence relation:

             a[k + 1]  =  floor(a[k] ^ 0.5)    if a[k] is even   ''' ''or'' '''
    a[k + 1]  =  floor(a[k] ^ 1.5)    if a[k] is odd

If a juggler sequence reaches 1, then all subsequent terms are equal to 1. This is known to be the case for initial terms up to 1,000,000 but it is not known whether all juggler sequences after that will eventually reach 1.

;Task:
Compute and show here the following statistics for juggler sequences with an initial term of a[n] where n is between '''20''' and '''39''' inclusive:

* l[n] - the number of terms needed to reach 1.
* h[n] - the maximum value reached in that sequence.
* i[n] - the index of the term (starting from 0) at which the maximum is (first) reached.

If your language supports ''big integers'' with an integer square root function, also compute and show here the same statistics for as many as you reasonably can of the following values for n:

113, 173, 193, 2183, 11229, 15065, 15845, 30817, 48443, 275485, 1267909, 2264915, 5812827

Those with fast languages and fast machines may also like to try their luck at n = 7110201.

However, as h[n] for most of these numbers is thousands or millions of digits long, show instead of h[n]:

* d[n] - the number of digits in h[n]

The results can be (partially) verified against the table here.

;Related tasks:
*   [[Hailstone sequence]]
*   [[Yellowstone sequence]]
*   [[Isqrt_(integer_square_root)_of_X]]

;See also:
* [[oeis:A007320]] Number of steps needed for Juggler sequence started at n to reach 1
* [[oeis:A094716]] Largest value in the Juggler sequence started at n

Solution:
def juggler(k) = k.even? ? Integer.sqrt(k) : Integer.sqrt(k*k*k)

(20..39).chain([113, 173, 193, 2183, 11229, 15065, 15845, 30817, 48443, 275485, 1267909, 2264915]).each do |k|
  k1 = k
  l = h = i = 0
  until k == 1 do
    h, i = k, l if k > h
    l += 1
    k =  juggler(k)
  end
  if k1 < 40 then
    puts "#{k1}: l[n] = #{l}, h[n] = #{h}, i[n] = #{i}"
  else
    puts "#{k1}: l[n] = #{l}, d[n] = #{h.to_s.size}, i[n] = #{i}"
  end
end


Julia set

Task
Generate and draw a Julia set.

;Related tasks
*   Mandelbrot Set

Solution:
def julia(c_real, c_imag)
  puts Complex(c_real, c_imag)
  -1.0.step(1.0, 0.04) do |v|
    puts -1.4.step(1.4, 0.02).map{|h| judge(c_real, c_imag, h, v)}.join
  end
end

def judge(c_real, c_imag, x, y)
  50.times do
    z_real = (x * x - y * y) + c_real
    z_imag = x * y * 2 + c_imag
    return " "  if z_real**2 > 10000
    x, y = z_real, z_imag
  end
  "#"
end

julia(-0.8, 0.156)


Jump anywhere

Imperative programs like to jump around, but some languages restrict these jumps. Many structured languages restrict their [[conditional structures]] and [[loops]] to ''local jumps'' within a function. Some assembly languages limit certain jumps or branches to a small range.

This task is to demonstrate a local jump and a global jump and the various other types of jumps that the language supports.
For the purpose of this task, the jumps need not be used for a single purpose and you have the freedom to use these jumps for different purposes.
You may also defer to more specific tasks, like [[Exceptions]] or [[Generator]].
This task provides a "grab bag" for several types of jumps. There are ''non-local jumps'' across function calls, or ''long jumps'' to anywhere within a program. Anywhere means not only to the tops of functions!

* Some languages can ''go to'' any global label in a program.
* Some languages can break multiple function calls, also known as ''unwinding the call stack''.
* Some languages can save a ''continuation''. The program can later continue from the same place. So you can jump anywhere, but only if you have a previous visit there (to save the continuation).

These jumps are not all alike.
A simple ''goto'' never touches the call stack.
A continuation saves the call stack, so you can continue a function call after it ends.

;Task:
Use your language to demonstrate the various types of jumps that it supports.

Because the possibilities vary by language, this task is not specific.
You have the freedom to use these jumps for different purposes.
You may also defer to more specific tasks, like [[Exceptions]] or [[Generator]].

Solution:
Ruby programs almost never use continuations. [[MRI]] copies the call stack when it saves or calls a continuation, so continuations are slow.

The next example abuses a continuation to solve [[FizzBuzz#Ruby]]. It is slower and more confusing than an ordinary loop.


Kaprekar numbers

A positive integer is a Kaprekar number if:
* It is   '''1'''     (unity)
* The decimal representation of its square may be split once into two parts consisting of positive integers which sum to the original number.
Note that a split resulting in a part consisting purely of 0s is not valid,
as 0 is not considered positive.

;Example Kaprekar numbers:
* 2223 is a Kaprekar number, as 2223 * 2223 = 4941729, 4941729 may be split to 494 and 1729, and 494 + 1729 = 2223.
* The series of Kaprekar numbers is known as A006886, and begins as 1, 9, 45, 55, ....

;Example process:
10000 (1002) splitting from left to right:
* The first split is [1, 0000], and is invalid; the 0000 element consists entirely of 0s, and 0 is not considered positive.
* Slight optimization opportunity: When splitting from left to right, once the right part consists entirely of 0s, no further testing is needed; all further splits would also be invalid.

;Task:
Generate and show all Kaprekar numbers less than 10,000.

;Extra credit:
Optionally, count (and report the count of) how many Kaprekar numbers are less than 1,000,000.

;Extra extra credit:
The concept of Kaprekar numbers is not limited to base 10 (i.e. decimal numbers);
if you can, show that Kaprekar numbers exist in other bases too.

For this purpose, do the following:
* Find all Kaprekar numbers for base 17 between 1 and 1,000,000 (one million);
* Display each of them in base 10 representation;
* Optionally, using base 17 representation (use letters 'a' to 'g' for digits 10(10) to 16(10)), display each of the numbers, its square, and where to split the square.

For example, 225(10) is "d4" in base 17, its square "a52g", and a5(17) + 2g(17) = d4(17), so the display would be something like:225   d4  a52g  a5 + 2g

;Reference:
* The Kaprekar Numbers by Douglas E. Iannucci (2000). PDF version

;Related task:
*   [[Casting out nines]]

Solution:
def kaprekar(n, base = 10)
  return [1, 1, 1, ""] if n == 1
  return if n*(n-1) % (base-1) != 0     # casting out nine
  sqr = (n ** 2).to_s(base)
  (1...sqr.length).each do |i|
    a = sqr[0 ... i]
    b = sqr[i .. -1]
    break if b.delete("0").empty?
    sum = a.to_i(base) + b.to_i(base)
    return n.to_s(base), sqr, a, b if sum == n
  end
  nil
end

count = 0
1.upto(10_000 - 1) do |i|
  if result = kaprekar(i)
    puts "%4d  %8d  %s + %s" % result
    count += 1
  end
end

10_000.upto(1_000_000 - 1) {|i| count += 1 if kaprekar(i)}
puts "#{count} kaprekar numbers under 1,000,000"

puts "\nbase17 kaprekar numbers under (base10)1,000,000"
base = 17
1.upto(1_000_000) do |decimal|
  if result = kaprekar(decimal, base)
    puts "%7s  %5s  %9s  %s + %s" % [decimal, *result]
  end
end


Kernighans large earthquake problem

Brian Kernighan, in a lecture at the University of Nottingham, described a problem on which this task is based.

;Problem:
You are given a a data file of thousands of lines; each of three `whitespace` separated fields: a date, a one word name and the magnitude of the event.

Example lines from the file would be lines like:
8/27/1883    Krakatoa            8.8
5/18/1980    MountStHelens       7.6
3/13/2009    CostaRica           5.1

;Task:
* Create a program or script invocation to find all the events with magnitude greater than 6
* Assuming an appropriate name e.g. "data.txt" for the file:
:# Either: Show how your program is invoked to process a data file of that name.
:# Or: Incorporate the file name into the program, (as it is assumed that the program is single use).

Solution:
ruby -nae "$F[2].to_f > 6 && print" data.txt

A more interesting problem. Print only the events whose magnitude is above average.

Contents of the file:

8/27/1883    Krakatoa            8.8
5/18/1980    MountStHelens       7.6
3/13/2009    CostaRica           5.1
2000-02-02  Foo               7.7
1959-08-08   Bar             6.2
1849-09-09  Pym                9.0

The command:

ruby -e"m=$<.to_a;f=->s{s.split[2].to_f};a=m.reduce(0){|t,s|t+f[s]}/m.size;puts m.select{|s|f[s]>a}" e.txt

Output:

8/27/1883    Krakatoa            8.8
5/18/1980    MountStHelens       7.6
2000-02-02  Foo               7.7
1849-09-09  Pym                9.0


Keyboard input/Obtain a Y or N response

Obtain a valid   '''Y'''   or   '''N'''   response from the [[input device::keyboard]].

The keyboard should be flushed, so that any outstanding key-presses are removed, preventing any existing   '''Y'''   or   '''N'''   key-press from being evaluated.

The response should be obtained as soon as   '''Y'''   or   '''N'''   are pressed, and there should be no need to press an   enter   key.

Solution:
def yesno
  begin
    system("stty raw -echo")
    str = STDIN.getc
  ensure
    system("stty -raw echo")
  end
  if str == "Y"
    return true
  elsif str == "N"
    return false
  else
    raise "Invalid character."
  end
end