10 HOME

100 N = 27
110 GOSUB 400"HAILSTONE
120 DEF FN L(I) = E(I + 4 * (I < 0))
130IFL=112AND(S(0)=27ANDS(1)=82ANDS(2)=41ANDS(3)=124)AND(FNL(M-3)=8ANDFNL(M-2)=4ANDFNL(M-1)=2ANDFNL(M)=1)THENPRINT"THE HAILSTONE SEQUENCE FOR THE NUMBER 27 HAS 112 ELEMENTS STARTING WITH 27, 82, 41, 124 AND ENDING WITH 8, 4, 2, 1"
140 PRINT
150 V = PEEK(37) + 1

200 N = 1
210 GOSUB 400"HAILSTONE
220 MN = 1
230 ML = L
240 FOR I = 2 TO 99999
250     N = I
260     GOSUB 400"HAILSTONE
270     IFL>MLTHENMN=I:ML=L:VTABV:HTAB1:PRINT "THE NUMBER " MN " HAS A HAILSTONE SEQUENCE LENGTH OF "L" WHICH IS THE LONGEST HAILSTONE SEQUENCE OF NUMBERS LESS THAN ";:Y=PEEK(37)+1:X=PEEK(36)+1
280     IF Y THEN VTAB Y : HTAB X : PRINTI+1;
290 NEXT I

300 END

400 M = 0
410 FOR L = 1 TO 1E38
420     IF L < 5 THEN S(L-1) = N
430     M = (M + 1) * (M < 3)
440     E(M) = N
450     IF N = 1 THEN RETURN
460     EVEN = INT(N/2)=N/2
470     IF EVEN THEN N=N/2
480     IF NOT EVEN THEN N = (3 * N) + 1
490 NEXT L : STOP


@echo off
setlocal enabledelayedexpansion
echo.
::Task #1
call :hailstone 111
echo Task #1: (Start:!sav!)
echo !seq!
echo.
echo Sequence has !cnt! elements.
echo.
::Task #2
call :hailstone 27
echo Task #2: (Start:!sav!)
echo !seq!
echo.
echo Sequence has !cnt! elements.
echo.
pause>nul
exit /b 0

::The Function
:hailstone
set num=%1
set seq=%1
set sav=%1
set cnt=0

:loop
set /a cnt+=1
if !num! equ 1 goto :eof
set /a isodd=%num%%%2
if !isodd! equ 0 goto divideby2

set /a num=(3*%num%)+1
set seq=!seq! %num%
goto loop

:divideby2
set /a num/=2
set seq=!seq! %num%
goto loop


   >@:N  q
>%"[email protected]
d~2~pL~1F{<T_


Collatz ← ⥊⊸{
  𝕨𝕊1: 𝕨;
  (𝕨⊸∾ 𝕊 ⊢) (2|𝕩)⊑⟨𝕩÷2⋄1+3×𝕩⟩
}

Collatz1 ← ⌽∘{
  1: ⟨1⟩;
  𝕩∾˜𝕊(2|𝕩)⊑⟨𝕩÷2⋄1+3×𝕩⟩
}

•Show Collatz1 5

•Show (⊑∾≠){𝕩⊑˜⊑⍒≠¨𝕩}Collatz1¨1+↕99999


(
  ( hailstone
  =   L len
    .   !arg:?L
      &   whl
        ' ( !arg:~1
          & (!arg*1/2:~/|3*!arg+1):?arg
          & !arg !L:?L
          )
      & (!L:? [?len&!len.!L)
  )
& ( reverse
  =   L e
    .   :?L
      & whl'(!arg:%?e ?arg&!e !L:?L)
      & !L
  )
& hailstone$27:(?len.?list)
& reverse$!list:?first4 [4 ? [-5 ?last4
& put$"Hailstone sequence starting with "
& put$!first4
& put$(str$(" has " !len " elements and ends with "))
& put$(!last4 \n)
& 1:?N
& 0:?max:?Nmax
&   whl
  ' ( !N+1:<100000:?N
    &   hailstone$!N
      : (   >!max:?max&!N:?Nmax
          | ?
        . ?
        )
    )
&   out
  $ ( str
    $ ( "The number <100000 with the longest hailstone sequence is "
        !Nmax
        " with "
        !max
        " elements."
      )
    )
);


hailstone = { num |
  sequence = [num]
  while { num != 1 }
    { true? num % 2 == 0
      { num = num / 2 }
      { num = num * 3 + 1 }
      sequence << num
    }

  sequence
}

#Check sequence for 27
seq = hailstone 27
true? (seq[0,3] == [27 82 41 124] && seq[-1, -4] == [8 4 2 1])
  { p "Sequence for 27 is correct" }
  { p "Sequence for 27 is not correct!" }

#Find longest sequence for numbers < 100,000
longest = [number: 0 length: 0]

1.to 99999 { index |
    seq = hailstone index
    true? seq.length > longest[:length]
      { longest[:length] = seq.length
        longest[:number] = index
        p "Longest so far: #{index} @ #{longest[:length]} elements"
      }

    index = index + 1
  }

p "Longest was starting from #{longest[:number]} and was of length #{longest[:length]}"


#include <stdio.h>
#include <stdlib.h>

int hailstone(int n, int *arry)
{
    int hs = 1;

    while (n!=1) {
        hs++;
        if (arry) *arry++ = n;
        n = (n&1) ? (3*n+1) : (n/2);
    }
    if (arry) *arry++ = n;
    return hs;
}

int main()
{
    int j, hmax = 0;
    int jatmax, n;
    int *arry;

    for (j=1; j<100000; j++) {
       n = hailstone(j, NULL);
       if (hmax < n) {
           hmax = n;
           jatmax = j;
       }
    }
    n = hailstone(27, NULL);
    arry = malloc(n*sizeof(int));
    n = hailstone(27, arry);

    printf("[ %d, %d, %d, %d, ...., %d, %d, %d, %d] len=%d\n",
        arry[0],arry[1],arry[2],arry[3],
        arry[n-4], arry[n-3], arry[n-2], arry[n-1], n);
    printf("Max %d at j= %d\n", hmax, jatmax);
    free(arry);

    return 0;
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Hailstone
{
    class Program
    {
        public static List<int> hs(int n,List<int> seq)
        {
            List<int> sequence = seq;
            sequence.Add(n);
            if (n == 1)
            {
                return sequence;
            }else{
                int newn = (n % 2 == 0) ? n / 2 : (3 * n) + 1;
                return hs(newn, sequence);
            }
        }

        static void Main(string[] args)
        {
            int n = 27;
            List<int> sequence = hs(n,new List<int>());
            Console.WriteLine(sequence.Count + " Elements");
            List<int> start = sequence.GetRange(0, 4);
            List<int> end = sequence.GetRange(sequence.Count - 4, 4);
            Console.WriteLine("Starting with : " + string.Join(",", start) + " and ending with : " + string.Join(",", end));
            int number = 0, longest = 0;
            for (int i = 1; i < 100000; i++)
            {
                int count = (hs(i, new List<int>())).Count;
                if (count > longest)
                {
                    longest = count;
                    number = i;
                }
            }
            Console.WriteLine("Number < 100000 with longest Hailstone seq.: " + number + " with length of " + longest);
       }
    }
}


#include <iostream>
#include <vector>
#include <utility>

std::vector<int> hailstone(int i)
{
    std::vector<int> v;
    while(true){
        v.push_back(i);
        if (1 == i) break;
        i = (i % 2) ? (3 * i + 1) : (i / 2);
    }
    return v;
}

std::pair<int,int> find_longest_hailstone_seq(int n)
{
    std::pair<int, int> maxseq(0, 0);
    int l;
    for(int i = 1; i < n; ++i){
        l = hailstone(i).size();
        if (l > maxseq.second) maxseq = std::make_pair(i, l);
    }
    return maxseq;
}

int main () {

// Use the routine to show that the hailstone sequence for the number 27
    std::vector<int> h27;
    h27 = hailstone(27);
// has 112 elements
    int l = h27.size();
    std::cout << "length of hailstone(27) is " << l;
// starting with 27, 82, 41, 124 and
    std::cout << " first four elements of hailstone(27) are ";
    std::cout << h27[0] << " " << h27[1] << " "
              << h27[2] << " " << h27[3] << std::endl;
// ending with 8, 4, 2, 1
    std::cout << " last four elements of hailstone(27) are "
              << h27[l-4] << " " << h27[l-3] << " "
              << h27[l-2] << " " << h27[l-1] << std::endl;

    std::pair<int,int> m = find_longest_hailstone_seq(100000);

    std::cout << "the longest hailstone sequence under 100,000 is " << m.first
              << " with " << m.second << " elements." <<std::endl;

    return 0;
}


shared void run() {

	{Integer*} hailstone(variable Integer n) {
		variable [Integer*] stones = [n];
		while(n != 1) {
			n = if(n.even) then n / 2 else 3 * n + 1;
			stones = stones.append([n]);
		}
		return stones;
	}

	value hs27 = hailstone(27);
	print("hailstone sequence for 27 is ``hs27.take(3)``...``hs27.skip(hs27.size - 3).take(3)`` with length ``hs27.size``");

	variable value longest = hailstone(1);
	for(i in 2..100k - 1) {
		value current = hailstone(i);
		if(current.size > longest.size) {
			longest = current;
		}
	}
	print("the longest sequence under 100,000 starts with ``longest.first else "what?"`` and has length ``longest.size``");
}


(deftemplate longest
  (slot bound)             ; upper bound for the range of values to check
  (slot next (default 2))  ; next value that needs to be checked
  (slot start (default 1)) ; starting value of longest sequence
  (slot len (default 1))   ; length of longest sequence
)

(deffacts startup
  (query 27)
  (longest (bound 100000))
)

(deffunction hailstone-next
  (?n)
  (if (evenp ?n)
    then (div ?n 2)
    else (+ (* 3 ?n) 1)
  )
)

(defrule extend-sequence
  ?hail <- (hailstone $?sequence ?tail&:(> ?tail 1))
  =>
  (retract ?hail)
  (assert (hailstone ?sequence ?tail (hailstone-next ?tail)))
)

(defrule start-query
  (query ?num)
  =>
  (assert (hailstone ?num))
)

(defrule result-query
  (query ?num)
  (hailstone ?num $?sequence 1)
  =>
  (bind ?sequence (create$ ?num ?sequence 1))
  (printout t "Hailstone sequence starting with " ?num ":" crlf)
  (bind ?len (length ?sequence))
  (printout t "  Length: " ?len crlf)
  (printout t "  First four: " (implode$ (subseq$ ?sequence 1 4)) crlf)
  (printout t "  Last four: " (implode$ (subseq$ ?sequence (- ?len 3) ?len)) crlf)
  (printout t crlf)
)

(defrule longest-create-next-hailstone
  (longest (bound ?bound) (next ?next))
  (test (<= ?next ?bound))
  (not (hailstone ?next $?))
  =>
  (assert (hailstone ?next))
)

(defrule longest-check-next-hailstone
  ?longest <- (longest (bound ?bound) (next ?next) (start ?start) (len ?len))
  (test (<= ?next ?bound))
  ?hailstone <- (hailstone ?next $?sequence 1)
  =>
  (retract ?hailstone)
  (bind ?thislen (+ 2 (length ?sequence)))
  (if (> ?thislen ?len) then
    (modify ?longest (start ?next) (len ?thislen) (next (+ ?next 1)))
    else
    (modify ?longest (next (+ ?next 1)))
  )
)

(defrule longest-finished
  (longest (bound ?bound) (next ?next) (start ?start) (len ?len))
  (test (> ?next ?bound))
  =>
  (printout t "The number less than " ?bound " that has the largest hailstone" crlf)
  (printout t "sequence is " ?start " with a length of " ?len "." crlf)
  (printout t crlf)
)


(defn hailstone-seq [n]
  {:pre [(pos? n)]}
  (lazy-seq
   (cond (= n 1)   '(1)
         (even? n) (cons n (hailstone-seq (/ n 2)))
         :else     (cons n (hailstone-seq (+ (* n 3) 1))))))

(let [hseq (hailstone-seq 27)]
  (->  hseq count      (= 112)            assert)
  (->> hseq (take 4)   (= [27 82 41 124]) assert)
  (->> hseq (drop 108) (= [8 4 2 1])      assert))

(let [{max-i :num, max-len :len}
      (reduce #(max-key :len %1 %2)
              (for [i (range 1 100000)]
                {:num i, :len (count (hailstone-seq i))}))]
  (println "Maximum length" max-len "was found for hailstone(" max-i ")."))


% Generate the hailstone sequence for a number
hailstone = iter (n: int) yields (int)
    while true do
        yield(n)
        if n=1 then break end
        if n//2 = 0 then
            n := n/2
        else
            n := 3*n + 1
        end
    end
end hailstone

% Make an array from an iterator
iter_array = proc [T,U: type] (i: itertype (U) yields (T), s: U) returns (array[T])
    arr: array[T] := array[T]$[]
    for item: T in i(s) do array[T]$addh(arr, item) end
    return(arr)
end iter_array

start_up = proc ()
    po: stream := stream$primary_output()

    % Generate the hailstone sequence for 27
    h27: array[int] := iter_array[int,int](hailstone, 27)
    lo27: int := array[int]$low(h27)
    hi27: int := array[int]$high(h27)

    stream$putl(po, "The hailstone sequence for 27 has "
                 || int$unparse(array[int]$size(h27)) || " elements.")
    stream$puts(po, "The first 4 elements are:")
    for i: int in int$from_to(lo27, lo27+3) do
        stream$puts(po, " " || int$unparse(h27[i]))
    end
    stream$puts(po, ", and the last 4 elements are:")
    for i: int in int$from_to(hi27-3, hi27) do
        stream$puts(po, " " || int$unparse(h27[i]))
    end
    stream$putl(po, "")

    % Find whichever sequence < 100 000 has the longest sequence
    maxnum: int := 0
    maxlen: int := 0

    for i: int in int$from_to(1, 99999) do
        len: int := array[int]$size(iter_array[int,int](hailstone, i))
        if len > maxlen then
            maxnum, maxlen := i, len
        end
    end

    stream$putl(po, int$unparse(maxnum)
                 || " has the longest hailstone sequence < 100000: "
                 || int$unparse(maxlen))
end start_up


       identification division.
       program-id. hailstones.
       remarks. cobc -x hailstones.cob.

       data division.
       working-storage section.
       01 most                 constant as 1000000.
       01 coverage             constant as 100000.
       01 stones               usage binary-long.
       01 n                    usage binary-long.
       01 storm                usage binary-long.

       01 show-arg             pic 9(6).
       01 show-default         pic 99 value 27.
       01 show-sequence        usage binary-long.
       01 longest              usage binary-long occurs 2 times.

       01 filler.
          05 hail              usage binary-long
                               occurs 0 to most depending on stones.
       01 show                 pic z(10).
       01 low-range            usage binary-long.
       01 high-range           usage binary-long.
       01 range                usage binary-long.

       01 remain               usage binary-long.
       01 unused               usage binary-long.

       procedure division.
       accept show-arg from command-line
       if show-arg less than 1 or greater than coverage then
           move show-default to show-arg
       end-if
       move show-arg to show-sequence

       move 1 to longest(1)
       perform hailstone varying storm
                         from 1 by 1 until storm > coverage
       display "Longest at: " longest(2) " with " longest(1) " elements"
       goback.

      *> **************************************************************
       hailstone.
       move 0 to stones
       move storm to n
       perform until n equal 1
           if stones > most then
               display "too many hailstones" upon syserr
               stop run
           end-if

           add 1 to stones
           move n to hail(stones)
           divide n by 2 giving unused remainder remain
           if remain equal 0 then
               divide 2 into n
           else
               compute n = 3 * n + 1
           end-if
       end-perform
       add 1 to stones
       move n to hail(stones)

       if stones > longest(1) then
           move stones to longest(1)
           move storm to longest(2)
       end-if

       if storm equal show-sequence then
           display show-sequence ": " with no advancing
           perform varying range from 1 by 1 until range > stones
               move 5 to low-range
               compute high-range = stones - 4
               if range < low-range or range > high-range then
                   move hail(range) to show
                   display function trim(show) with no advancing
                   if range < stones then
                       display ", " with no advancing
                   end-if
               end-if
               if range = low-range and stones > 8 then
                   display "..., " with no advancing
               end-if
           end-perform
           display ": " stones " elements"
       end-if
       .

       end program hailstones.


hailstone = (n) ->
  if n is 1
    [n]

  else if n % 2 is 0
    [n].concat hailstone n/2

  else
    [n].concat hailstone (3*n) + 1

h27 = hailstone 27
console.log "hailstone(27) = #{h27[0..3]} ... #{h27[-4..]} (length: #{h27.length})"

maxlength = 0
maxnums = []

for i in [1..100000]
  seq = hailstone i

  if seq.length is maxlength
    maxnums.push i
  else if seq.length > maxlength
    maxlength = seq.length
    maxnums = [i]

console.log "Max length: #{maxlength}; numbers generating sequences of this length: #{maxnums}"


(defun hailstone (n)
  (cond ((= n 1) '(1))
	((evenp n) (cons n (hailstone (/ n 2))))
	(t (cons n (hailstone (+ (* 3 n) 1))))))

(defun longest (n)
  (let ((k 0) (l 0))
    (loop for i from 1 below n do
	 (let ((len (length (hailstone i))))
	   (when (> len l) (setq l len k i)))
	 finally (format t "Longest hailstone sequence under ~A for ~A, having length ~A." n k l))))


include "cowgol.coh";

# Generate the hailstone sequence for the given N and return the length.
# If a non-NULL pointer to a buffer is given, then store the sequence there.
sub hailstone(n: uint32, buf: [uint32]): (len: uint32) is
    len := 0;
    loop
        if buf != 0 as [uint32] then
            [buf] := n;
            buf := @next buf;
        end if;
        len := len + 1;
        if n == 1 then
            break;
        elseif n & 1 == 0 then
            n := n / 2;
        else
            n := 3*n + 1;
        end if;
    end loop;
end sub;

# Generate hailstone sequence for 27
var h27: uint32[113];
var h27len := hailstone(27, &h27[0]);

# Print information about it
print("The hailstone sequence for 27 has ");
print_i32(h27len);
print(" elements.\nThe first 4 elements are:");
var n: @indexof h27 := 0;
while n < 4 loop
    print_char(' ');
    print_i32(h27[n]);
    n := n + 1;
end loop;
print(", and the last 4 elements are:");
n := h27len as @indexof h27 - 4;
while n as uint32 < h27len loop
    print_char(' ');
    print_i32(h27[n]);
    n := n + 1;
end loop
print(".\n");

# Find longest hailstone sequence < 100,000
var i: uint32 := 1;
var max_i := i;
var len: uint32 := 0;
var max_len := len;
while i < 100000 loop
    len := hailstone(i, 0 as [uint32]);
    if len > max_len then
        max_i := i;
        max_len := len;
    end if;
    i := i + 1;
end loop;

print_i32(max_i);
print(" has the longest hailstone sequence < 100000: ");
print_i32(max_len);
print_nl();


def hailstone(n)
    seq = [n]
    until n == 1
        n = n.even? ? n // 2 : n * 3 + 1
        seq << n
    end
    seq
end

max_len = (1...100_000).max_by{|n| hailstone(n).size }
max = hailstone(max_len)
puts ([max_len, max.size, max.max, max.first(4), max.last(4)])
# => [77031, 351, 21933016, [77031, 231094, 115547, 346642], [8, 4, 2, 1]]

twenty_seven = hailstone(27)
puts ([twenty_seven.size, twenty_seven.first(4), max.last(4)])
# => [112, [27, 82, 41, 124], [8, 4, 2, 1]]


import std.stdio, std.algorithm, std.range, std.typecons;

auto hailstone(uint n) pure nothrow {
  auto result = [n];
  while (n != 1) {
    n = (n & 1) ? (n * 3 + 1) : (n / 2);
    result ~= n;
  }
  return result;
}

void main() {
  enum M = 27;
  immutable h = M.hailstone;
  writeln("hailstone(", M, ")= ", h[0 .. 4], " ... " , h[$ - 4 .. $]);
  writeln("Length hailstone(", M, ")= ", h.length);

  enum N = 100_000;
  immutable p = iota(1, N)
                .map!(i => tuple(i.hailstone.length, i))
                .reduce!max;
  writeln("Longest sequence in [1,", N, "]= ",p[1]," with len ",p[0]);
}


List<int> hailstone(int n) {
  if(n<=0) {
    throw new IllegalArgumentException("start value must be >=1)");
  }
  Queue<int> seq=new Queue<int>();
  seq.add(n);
  while(n!=1) {
    n=n%2==0?(n/2).toInt():3*n+1;
    seq.add(n);
  }
  return new List<int>.from(seq);
}

// apparently List is missing toString()
String iterableToString(Iterable seq) {
  String str="[";
  Iterator i=seq.iterator();
  while(i.hasNext()) {
    str+=i.next();
    if(i.hasNext()) {
      str+=",";
    }
  }
  return str+"]";
}

main() {
  for(int i=1;i<=10;i++) {
    print("h($i)="+iterableToString(hailstone(i)));
  }
  List<int> h27=hailstone(27);
  List<int> first4=h27.getRange(0,4);
  print("first 4 elements of h(27): "+iterableToString(first4));
  Expect.listEquals([27,82,41,124],first4);

  List<int> last4=h27.getRange(h27.length-4,4);
  print("last 4 elements of h(27): "+iterableToString(last4));
  Expect.listEquals([8,4,2,1],last4);

  print("length of sequence h(27): "+h27.length);
  Expect.equals(112,h27.length);

  int seq,max=0;
  for(int i=1;i<=100000;i++) {
    List<int> h=hailstone(i);
    if(h.length>max) {
      max=h.length;
      seq=i;
    }
  }
  print("up to 100000 the sequence h($seq) has the largest length ($max)");
}


$ n = f$integer( p1 )
$ i = 1
$ loop:
$  if p2 .nes. "QUIET" then $ s'i = n
$  if n .eq. 1 then $ goto done
$  i = i + 1
$  if .not. n
$  then
$   n = n / 2
$  else
$   if n .gt. 715827882 then $ exit  ! avoid overflowing
$   n = 3 * n + 1
$  endif
$  goto loop
$ done:
$ if p2 .nes. "QUIET"
$ then
$  penultimate_i = i - 1
$  antepenultimate_i = i - 2
$  preantepenultimate_i = i - 3
$  write sys$output "sequence has ", i, " elements starting with ", s1, ", ", s2, ", ", s3, ", ", s4, " and ending with ", s'preantepenultimate_i, ", ", s'antepenultimate_i, ", ", s'penultimate_i, ", ", s'i
$ endif
$ sequence_length == i


program ShowHailstoneSequence;

{$APPTYPE CONSOLE}

uses SysUtils, Generics.Collections;

procedure GetHailstoneSequence(aStartingNumber: Integer; aHailstoneList: TList<Integer>);
var
  n: Integer;
begin
  aHailstoneList.Clear;
  aHailstoneList.Add(aStartingNumber);
  n := aStartingNumber;

  while n <> 1 do
  begin
    if Odd(n) then
      n := (3 * n) + 1
    else
      n := n div 2;
    aHailstoneList.Add(n);
  end;
end;

var
  i: Integer;
  lList: TList<Integer>;
  lMaxSequence: Integer;
  lMaxLength: Integer;
begin
  lList := TList<Integer>.Create;
  try
    GetHailstoneSequence(27, lList);
    Writeln(Format('27: %d elements', [lList.Count]));
    Writeln(Format('[%d,%d,%d,%d ... %d,%d,%d,%d]',
      [lList[0], lList[1], lList[2], lList[3],
      lList[lList.Count - 4], lList[lList.Count - 3], lList[lList.Count - 2], lList[lList.Count - 1]]));
    Writeln;

    lMaxSequence := 0;
    lMaxLength := 0;
    for i := 1 to 100000 do
    begin
      GetHailstoneSequence(i, lList);
      if lList.Count > lMaxLength then
      begin
        lMaxSequence := i;
        lMaxLength := lList.Count;
      end;
    end;
    Writeln(Format('Longest sequence under 100,000: %d with %d elements', [lMaxSequence, lMaxLength]));
  finally
    lList.Free;
  end;

  Readln;
end.


local hailstone:
	swap [ over ]
	while < 1 dup:
		if % over 2:
			#odd
			++ * 3
		else:
			#even
			/ swap 2
		swap push-through rot dup
	drop

if = (name) :(main):
	local :h27 hailstone 27
	!. = 112 len h27
	!. = 27 h27! 0
	!. = 82 h27! 1
	!. = 41 h27! 2
	!. = 124 h27! 3
	!. = 8 h27! 108
	!. = 4 h27! 109
	!. = 2 h27! 110
	!. = 1 h27! 111

	local :max 0
	local :maxlen 0
	for i range 1 99999:
		dup len hailstone i
		if < maxlen:
			set :maxlen
			set :max i
		else:
			drop
	!print( "number: " to-str max ", length: " to-str maxlen )
else:
	@hailstone


(lib 'hash)
(lib 'sequences)
(lib 'compile)

(define (hailstone n)
(when (> n 1)
	(if (even? n) (/ n 2) (1+ (* n 3)))))

(define H (make-hash))

;; (iterator/f seed f) returns seed, (f seed) (f(f seed)) ...

(define (hlength seed)
	(define collatz (iterator/f hailstone seed))
	(or
	   (hash-ref H seed) ;; known ?
	   (hash-set H seed
	      (for ((i (in-naturals)) (h collatz))
              ;; add length of subsequence if already known
	      #:break (hash-ref H h) => (+ i (hash-ref H h))
	      (1+ i)))))

(define (task (nmax 100000))
	(for ((n [1 .. nmax])) (hlength n)) ;; fill hash table

	(define hmaxlength (apply max (hash-values H)))
	(define hmaxseed (hash-get-key H hmaxlength))
	(writeln 'maxlength= hmaxlength 'for hmaxseed))


 [Hailstone (or Collatz) task for Rosetta Code.
  EDSAC program, Initial Orders 2.]

 [This program shows how subroutines can be called via the
  phi, H, N, ..., V parameters, so that the code doesn't have
  to be changed if the subroutines are moved about in store.
  See Wilkes, Wheeler and Gill, 1951 edition, page 18.]

 [Library subroutine P7, prints long strictly positive integer;
  10 characters, right justified, padded left with spaces.
  Input: 0D = integer to be printed.
  Closed, even; 35 storage locations; working position 4D.]
            T   55 K  [call subroutine via V parameter]
            P   56 F  [address of subroutine]
            E   25 K
            T      V
   [email protected]#@[email protected]@[email protected]@SFLDUFOFFFSFL4F
   [email protected]@XFT28#[email protected][email protected]@

  [Subroutine to print a string placed after the subroutine call.
  One location per character, with character in top 5 bits.
  Last character flagged by having bit 0 set.
  17 locations, workspace 0F.]
            T   54 K  [call subroutine via C parameter]
            P   91 F  [address of subroutine]
            E   25 K
            T      C
   [email protected]@[email protected][email protected]@[email protected]@EFV2047F

 [************ Rosetta Code task ************
  Subroutine to generate and optionally store the hailstone
  (Collatz) sequence for the passed-in initial term n.
  Input:  4D = n, 35-bit positive integer
          6F = start address of sequence if stored;
               must be even; 0 = don't store
  Output: 7F = number of terms in sequence, or -1 if error
  Workspace: 0D (general), 8D (term of sequence)
  Must be loaded at an even address.]
            T   45 K  [call subroutine via H parameter]
            P  108 F  [address of subroutine]
            E   25 K
            T      H
            G      K
            A    3 F
            T   46 @
            H   54#@  [mult reg := 1 to test odd/even]
            A    4 D  [load n passed in by caller]
            T    8 D  [term := n]
            A   54 @  [load 1 (single)]
            T    7 F  [include initial term in count]
            A    6 F  [load address for store]
            S   56 @  [test for 0; allow for pre-inc]
            G   11 @  [skip next if storing not wanted]
            A   12 @  [make 'T addr D' order]
     [11]   T   21 @  [plant T order, or -ve value if not storing
                         (note that a T order is +ve as an integer)]
        [Loop: deal with current term in sequence
         First store it, if user requested that]
     [12]   T      D  [clear acc; also serves to make 'T addr D' order]
            A   21 @  [load T order to store term]
            G   22 @  [jump if caller doesn't want store]
            A   56 @  [pre-inc the address]
            U   21 @  [update T order]
            S   51 @  [check not gone beyond max EDSAC address]
            E   47 @  [error exit if it has]
            T      F  [clear acc]
            A    8 D  [load term]
     [21]   T      D  [store]
     [22]   T      F  [clear acc]
            A   54#@  [load 1 (double)]
            S    8 D  [1 - term]
            E   46 @  [if term = 1, jump out with acc = 0]
            T      F  [clear acc]
            C    8 D  [acc := term AND 1]
            S   54#@  [test whether 0 or 1]
            G   38 @  [jump if term is even]
         [Here if term is odd; acc = 0]
            A    8 D  [load term]
            S   52#@  [guard against numeric overflow]
            E   47 @  [jump if overflow]
            A   52#@  [restore term after test]
            L      D  [term*2]
            A    8 D  [term*3]
            A   54#@  [plus 1]
            E   41 @  [join common code]
         [Here if term is even]
     [38]   T      F  [clear acc]
            A    8 D  [load term]
            R      D  [term/2]
         [Common code, acc = new term]
     [41]   T    8 D  [store new term]
            A    7 F  [load count]
            A   54 @  [add 1]
            T    7 F  [update count]
            E   12 @  [loop back]
        [Here when sequence has reached 1
         Assume jump here with acc = 0]
     [46]   E      F  [return with acc = 0]
     [47]   T      F  [here on error]
            S   54 F  [acc := -1]
            T    7 F  [return that as count]
            E   46 @
   [Arrange the following to ensure even addresses for 35-bit values]
     [51]   T 1024 F  [for checking valid address]
     [52]   H  682 DT  682 D  [(2^34 - 1)/3]
     [54]   P      DP      F  [1]
     [56]   P    2 F  [to change addresses by 2]

        [Program to demonstrate Rosetta Code subroutine]
            T  180 K
            G      K
  [Double constants]
           [P 500 F  P F]  [maximum n = 1000"]
      [0]   & 848 F PF     [maximum n = 100000]
      [2]   P  13 D PF     [n = 27 as demo of sequence]
      [4]   P     D PF     [1]
  [Double variables]
      [6]   P  F P F  [n, start of Collatz sequence]
      [8]   P  F P F  [n with maximum count]
  [Single constants]
     [10]   P  400 F  [where to store sequence]
     [11]   P    2 F  [to change addresses by 2]
     [12]   @      F  [carriage return]
     [13]   &      F  [line feed]
     [14]   K 4096 F  [null char]
     [15]   A      D  [used for maiking 'A addr D' order]
     [16]   P    8 F  [ used for adding 8 to address]
  [Single variables]
     [17]   P      F  [maximum number of terms]
     [18]   P      F  [temporary store]
     [19]   P      F  [marks end of printing]

 [Subroutine to print 4 numbers starting at address in 6F.
  Prints new line (CR, LF) at end.]
     [20]   A    3 F  [plant link for return]
            T   40 @
            A    6 F  [load start address]
            A   15 @  [make 'A addr D' order]
            A   16 @  [inc address by 8 (4 double values)]
            U   19 @  [store as test for end]
            S   16 @  [restore 'A addr D' order for start]
     [27]   U   31 @  [plant 'A addr D' order in code]
            S   19 @  [test for end]
            E   38 @  [out if so]
            T      F  [clear acc]
     [31]   A      D  [load number]
            T      D  [to 0D for printing]
     [33]   A   33 @  [call print subroutine]
            G      V
            A   31 @  [load 'A addr D' order]
            A   11 @  [inc address to next double value]
            G   27 @  [loop back]
     [38]   O   12 @  [here when done, print CR LF]
            O   13 @
     [40]   E      F  [return]

         [Enter with acc = 0]
         [PART 1]
     [41]   A    2#@  [load demo value of n]
            T    4 D  [to 4D for subroutine]
            A   10 @  [address to store sequence]
            T    6 F  [to 6F for subroutine]
     [45]   A   45 @  [call subroutine to generate sequence]
            G      H
            A    7 F  [load length of sequence]
            G  198 @  [out if error]
            T   18 @
         [Print result]
     [50]   A   50 @  [print 'start' message]
            G      C
            K2048F SF TF AF RF TF !F !F #D
            A    2#@  [load demo value of n]
            T      D  [to 0D for printing]
     [63]   A   63 @  [print demo n]
            G      V
     [65]   A   65 @  [print 'length' string]
            G      C
            K2048F @F &F LF EF NF GF TF HF !F #D
            T      D  [ensure 1F and sandwich bit are 0]
            A   18 @  [load length]
            T      F  [to 0F (effectively 0D) for printing]
     [81]   A   81 @
            G      V
     [83]   A   83 @  [print 'first and last four' string]
            G      C
            K2048F @F &F FF IF RF SF TF !F AF NF DF !F LF AF SF TF !F FF OF UF RF @F &F #D
            A   18 @  [load length of sequence]
            L    1 F  [times 4]
            A    6 F  [make address of last 4]
            S   16 @
            T   18 @  [store address of last 4]
    [115]   A  115 @  [print first 4 terms]
            G   20 @
            A   18 @  [retrieve address of last 4]
            T    6 F  [pass as parameter]
    [119]   A  119 @  [print last 4 terms]
            G   20 @

         [PART 2]
            T      F
            T   17 @  [max count := 0]
            T    6#@  [n := 0]
         [Loop: update n, start new sequence]
    [124]   T      F  [clear acc]
            A    6#@  [load n]
            A    4#@  [add 1 (double)]
            U    6#@  [update n]
            T    4 D  [n to 4D for subroutine]
            T    6 F  [say no store]
    [130]   A  130 @  [call subroutine to generate sequence]
            G      H
            A    7 F  [load count returned by subroutine]
            G  198 @  [out if error]
            S   17 @  [compare with max count so far]
            G  140 @  [skip if less]
            A   17 @  [restore count after test]
            T   17 @  [update max count]
            A    6#@  [load n]
            T    8#@  [remember n that gave max count]
    [140]   T      F  [clear acc]
            A    6#@  [load n just done]
            S     #@  [compare with max(n)]
            G  124 @  [loop back if n < max(n)
                       else fall through with acc = 0]
         [Here whan reached maximum n. Print result.]
    [144]   A  144 @  [print 'max n' message]
            G      C
            K2048F MF AF XF !F NF !F !F #D
            A     #@  [load maximum n]
            T      D  [to 0D for printing]
    [157]   A  157 @  [call print subroutine]
            G      V
    [159]   A  159 @  [print 'max len' message]
            G      C
            K2048F @F &F MF AF XF !F LF EF NF #D
            T      D  [clear 1F and sandwich bit]
            A   17 @  [load max count (single)]
            T      F  [to 0F, effectively to 0D]
    [175]   A  175 @  [call print subroutine]
            G      V
    [177]   A  177 @  [print 'at n =' message]
            G      C
            K2048F @F &F AF TF !F NF !F #F VF !D
            A    8#@  [load n for which max count occurred]
            T      D  [to 0D for printing]
    [192]   A  192 @  [call print subroutine]
            G      V
    [194]   O   12 @  [print CR, LF]
            O   13 @
            O   14 @  [print null to flush teleprinter buffer]
            Z      F  [stop]
        [Here if term would overflow EDSAC 35-bit value.
         With a maximum n of 100,000 this doesn't happen.]
    [198]   A  198 @  [print 'overflow' message]
            G      C
            K2048F @F &F OF VF EF RF FF LF OF WD
            E  194 @  [jump to exit]

            E   41 Z  [define entry point]
            P      F  [acc = 0 on entry]


import "prelude.eg"

namespace Hailstone (

    using System
    using List

    def even = [ N -> (N%2) == 0 ]

    def hailstone =
        [ 1 -> {1}
        | N -> if even N then cons N (hailstone (N/2))
               else cons N (hailstone (N * 3 + 1)) ]

    def hailpair =
        [ N -> (N, length (hailstone N)) ]

    def hailmax =
        [ (N, NMAX), (M, MMAX) -> if (NMAX < MMAX) then (M, MMAX) else (N, NMAX) ]

    def largest =
        [ 1 -> (1, 1)
        | N ->
            let M0 = hailpair N in
            let M1 = largest (N - 1) in
                hailmax M0 M1 ]
)

using System
using List
using Hailstone

def task0 = let H27 = hailstone 27 in length H27

def task1 =
    let H27 = hailstone 27 in
    let L   = length H27 in
        (take 4 H27, drop (L - 4) H27)

def task2 = largest 100000

def main = (task0, task1, task2)


class
	APPLICATION

create
	make

feature

	make
		local
			test: LINKED_LIST [INTEGER]
			count, number, te: INTEGER
		do
			create test.make
			test := hailstone_sequence (27)
			io.put_string ("There are " + test.count.out + " elements in the sequence for the number 27.")
			io.put_string ("%NThe first 4 elements are: ")
			across
				1 |..| 4 as t
			loop
				io.put_string (test [t.item].out + "%T")
			end
			io.put_string ("%NThe last 4 elements are: ")
			across
				(test.count - 3) |..| test.count as t
			loop
				io.put_string (test [t.item].out + "%T")
			end
			across
				1 |..| 99999 as c
			loop
				test := hailstone_sequence (c.item)
				te := test.count
				if te > count then
					count := te
					number := c.item
				end
			end
			io.put_string ("%NThe longest sequence for numbers below 100000 is " + count.out + " for the number " + number.out + ".")
		end

	hailstone_sequence (n: INTEGER): LINKED_LIST [INTEGER]
			-- Members of the Hailstone Sequence starting from 'n'.
		require
			n_is_positive: n > 0
		local
			seq: INTEGER
		do
			create Result.make
			from
				seq := n
			until
				seq = 1
			loop
				Result.extend (seq)
				if seq \\ 2 = 0 then
					seq := seq // 2
				else
					seq := ((3 * seq) + 1)
				end
			end
			Result.extend (seq)
		ensure
			sequence_terminated: Result.last = 1
		end

end


import system'collections;
import extensions;

const int maxNumber = 100000;

Hailstone(int n,Map<int,int> lengths)
{
    if (n == 1)
    {
        ^ 1
    };

    while (true)
    {
        if (lengths.containsKey(n))
        {
            ^ lengths[n]
        }
        else
        {
            if (n.isEven())
            {
                lengths[n] := 1 + Hailstone(n/2, lengths)
            }
            else
            {
                lengths[n] := 1 + Hailstone(3*n + 1, lengths)
            }
        }
    }
}

public program()
{
    int longestChain := 0;
    int longestNumber := 0;
    auto recursiveLengths := new Map<int,int>(4096,4096);

    for(int i := 1, i < maxNumber, i+=1)
    {
        var chainLength := Hailstone(i, recursiveLengths);
        if (longestChain < chainLength)
        {
               longestChain := chainLength;
               longestNumber := i
        }
    };

    console.printFormatted("max below {0}: {1} ({2} steps)", maxNumber, longestNumber, longestChain)
}


defmodule Hailstone do
  require Integer

  def step(1)                        , do: 0
  def step(n) when Integer.is_even(n), do: div(n,2)
  def step(n)                        , do: n*3 + 1

  def sequence(n) do
    Stream.iterate(n, &step/1) |> Stream.take_while(&(&1 > 0)) |> Enum.to_list
  end

  def run do
    seq27 = sequence(27)
    len27 = length(seq27)
    repr = String.replace(inspect(seq27, limit: 4) <> inspect(Enum.drop(seq27,len27-4)), "][", ", ")
    IO.puts "Hailstone(27) has #{len27} elements: #{repr}"

    {len, start} = Enum.map(1..100_000, fn(n) -> {length(sequence(n)), n} end) |> Enum.max
    IO.puts "Longest sequence starting under 100000 begins with #{start} and has #{len} elements."
  end
end

Hailstone.run


-module(hailstone).
-import(io).
-export([main/0]).

hailstone(1) -> [1];
hailstone(N) when N band 1 == 1 -> [N|hailstone(N * 3 + 1)];
hailstone(N) when N band 1 == 0 -> [N|hailstone(N div 2)].

max_length(Start, Stop) ->
    F = fun (N) -> {length(hailstone(N)), N} end,
    Lengths = lists:map(F, lists:seq(Start, Stop)),
    lists:max(Lengths).

main() ->
    io:format("hailstone(4): ~w~n", [hailstone(4)]),
    Seq27 = hailstone(27),
    io:format("hailstone(27) length: ~B~n", [length(Seq27)]),
    io:format("hailstone(27) first 4: ~w~n",
              [lists:sublist(Seq27, 4)]),
    io:format("hailstone(27) last 4: ~w~n",
              [lists:nthtail(length(Seq27) - 4, Seq27)]),
    io:format("finding maximum hailstone(N) length for 1 <= N <= 100000..."),
    {Length, N} = max_length(1, 100000),
    io:format(" done.~nhailstone(~B) length: ~B~n", [N, Length]).


PROGRAM ULAM

!$DOUBLE

PROCEDURE HAILSTONE(X,PRT%->COUNT)
   COUNT=1
   IF PRT% THEN PRINT(X,) END IF
   REPEAT
      IF X/2<>INT(X/2) THEN
          X=X*3+1
        ELSE
          X=X/2
      END IF
      IF PRT% THEN PRINT(X,) END IF
      COUNT=COUNT+1
   UNTIL X=1
   IF PRT% THEN PRINT END IF
END PROCEDURE

BEGIN
   HAILSTONE(27,TRUE->COUNT)
   PRINT("Sequence length for 27:";COUNT)
   MAX_COUNT=2
   NMAX=2
   FOR I=3 TO 100000 DO
      HAILSTONE(I,FALSE->COUNT)
      IF COUNT>MAX_COUNT THEN NMAX=I MAX_COUNT=COUNT END IF
   END FOR
   PRINT("Max. number is";NMAX;" with";MAX_COUNT;"elements")
END PROGRAM


function hailstone(atom n)
    sequence s
    s = {n}
    while n != 1 do
        if remainder(n,2)=0 then
            n /= 2
        else
            n = 3*n + 1
        end if
        s &= n
    end while
    return s
end function

function hailstone_count(atom n)
    integer count
    count = 1
    while n != 1 do
        if remainder(n,2)=0 then
            n /= 2
        else
            n = 3*n + 1
        end if
        count += 1
    end while
    return count
end function

sequence s
s = hailstone(27)
puts(1,"hailstone(27) =\n")
? s
printf(1,"len = %d\n\n",length(s))

integer max,imax,count
max = 0
for i = 2 to 1e5-1 do
    count = hailstone_count(i)
    if count > max then
        max = count
        imax = i
    end if
end for

printf(1,"The longest hailstone sequence under 100,000 is %d with %d elements.\n",
    {imax,max})


   In cell A1, place the starting number.
   In cell A2 enter this formula =IF(MOD(A1,2)=0,A1/2,A1*3+1)
   Drag and copy the formula down until 4, 2, 1


நிரல்பாகம்  hailstone ( எண் )
           பதிப்பி "=> ",எண் #hailstone seq
	    @( எண் == 1 )   ஆனால்
	        பின்கொடு எண்
	    முடி

	      @( (எண்%2) == 1 )  ஆனால்
	      	   hailstone( 3*எண் + 1)
              இல்லை
	           hailstone( எண்/2 )
              முடி
முடி

எண்கள் = [5,17,19,23,37]
@(எண்கள் இல் இவ்வெண்) ஒவ்வொன்றாக
   பதிப்பி "****** calculating hailstone seq for ",இவ்வெண்," *********"
   hailstone( இவ்வெண் )
   பதிப்பி "**********************************************"
முடி


let rec hailstone n = seq {
  match n with
  | 1                -> yield 1
  | n when n % 2 = 0 -> yield n; yield! hailstone (n / 2)
  | n                -> yield n; yield! hailstone (n * 3 + 1)
}

let hailstone27 = hailstone 27 |> Array.ofSeq
assert (Array.length hailstone27 = 112)
assert (hailstone27.[..3] = [|27;82;41;124|])
assert (hailstone27.[108..] = [|8;4;2;1|])

let maxLen, maxI = Seq.max <| seq { for i in 1..99999 -> Seq.length (hailstone i), i}
printfn "Maximum length %d was found for hailstone(%d)" maxLen maxI


! rosetta/hailstone/hailstone.factor
USING: arrays io kernel math math.ranges prettyprint sequences vectors ;
IN: rosetta.hailstone

: hailstone ( n -- seq )
    [ 1vector ] keep
    [ dup 1 number= ]
    [
        dup even? [ 2 / ] [ 3 * 1 + ] if
        2dup swap push
    ] until
    drop ;

<PRIVATE
: main ( -- )
    27 hailstone dup dup
    "The hailstone sequence from 27:" print
    "  has length " write length .
    "  starts with " write 4 head [ unparse ] map ", " join print
    "  ends with " write 4 tail* [ unparse ] map ", " join print

    ! Maps n => { length n }, and reduces to longest Hailstone sequence.
    1 100000 [a,b)
    [ [ hailstone length ] keep 2array ]
    [ [ [ first ] [email protected] > ] most ] map-reduce
    first2
    "The hailstone sequence from " write pprint
    " has length " write pprint "." print ;
PRIVATE>

MAIN: main


Array g[2]

Func Collatz(n, d) =
    {Runs the Collatz procedure for the number n and returns the number of steps.}
    {If d is nonzero, prints the terms in the sequence.}
    steps := 1;
    while n>1 do
        if n|2=0 then n:=n/2 else n:=3n+1 fi;
        if d then !!n fi;
        steps := steps + 1
    od;
    steps.

Function LongestTo(n) =
    {Finds the number up to n for which the Collatz algorithm takes the most number of steps.}
    {The result is stored in the array [g]: g[1] is the number, g[2] is how many steps it takes.}
    champ:=0;
    record:=0;
    for i = 1, n do
        q:=Collatz(i, 0);
        if q > record then
            champ:=i; record:=q; fi;
    od;
    g[1]:=champ;
    g[2]:=record;
    .


: hail-next ( n -- n )
  dup 1 and if 3 * 1+ else 2/ then ;
: .hail ( n -- )
  begin dup . dup 1 > while hail-next repeat drop ;
: hail-len ( n -- n )
  1 begin over 1 > while swap hail-next swap 1+ repeat nip ;

27 hail-len . cr
27 .hail cr

: longest-hail ( max -- )
  0 0 rot 1+ 1 do    ( n length )
    i hail-len 2dup < if
      nip nip i swap
    else drop then
  loop
  swap . ." has hailstone sequence length " . ;

100000 longest-hail


program Hailstone
  implicit none

  integer :: i, maxn
  integer :: maxseqlen = 0, seqlen
  integer, allocatable :: seq(:)

  call hs(27, seqlen)
  allocate(seq(seqlen))
  call hs(27, seqlen, seq)
  write(*,"(a,i0,a)") "Hailstone sequence for 27 has ", seqlen, " elements"
  write(*,"(a,4(i0,a),3(i0,a),i0)") "Sequence = ", seq(1), ", ", seq(2), ", ", seq(3), ", ", seq(4), " ...., ",  &
                                     seq(seqlen-3), ", ", seq(seqlen-2), ", ", seq(seqlen-1), ", ", seq(seqlen)

  do i = 1, 99999
    call hs(i, seqlen)
    if (seqlen > maxseqlen) then
      maxseqlen = seqlen
      maxn = i
    end if
  end do
  write(*,*)
  write(*,"(a,i0,a,i0,a)") "Longest sequence under 100000 is for ", maxn, " with ", maxseqlen, " elements"

  deallocate(seq)

contains

subroutine hs(number, length, seqArray)
  integer, intent(in)  :: number
  integer, intent(out) :: length
  integer, optional, intent(inout) :: seqArray(:)
  integer :: n

  n = number
  length = 1
  if(present(seqArray)) seqArray(1) = n
  do while(n /= 1)
    if(mod(n,2) == 0) then
      n = n / 2
    else
      n = n * 3 + 1
    end if
    length = length + 1
    if(present(seqArray)) seqArray(length) = n
  end do
end subroutine

end program


module Hailstone where

import Data.List (maximumBy)

hailstone :: Int -> [Int]
hailstone 1             = [1]
hailstone n | even n    = n : hailstone (n `div` 2)
            | otherwise = n : hailstone (n * 3 + 1)

withResult :: (t -> t1) -> t -> (t1, t)
withResult f x = (f x, x)

main :: IO ()
main = do
 let h27 = hailstone 27
 putStrLn $ show $ length h27
 let h4 = show $ take 4 h27
 let t4 = show $ drop (length h27 - 4) h27
 putStrLn ("hailstone 27: " ++ h4 ++ " ... " ++ t4)
 putStrLn $ show $ maximumBy (comparing fst) $ map (withResult (length . hailstone)) [1..100000]


hailstone[n] :=
{
   results = new array

   while n != 1
   {
      results.push[n]
      if n mod 2 == 0    // n is even?
         n = n / 2
      else
         n = (3n + 1)
   }

   results.push[1]
   return results
}

longestLen = 0
longestN = 0
for n = 1 to 100000
{
   seq = hailstone[n]
   if length[seq] > longestLen
   {
      longestLen = length[seq]
      longestN = n
   }
}

println["$longestN has length $longestLen"]


def
  hailstone( 1 ) = [1]
  hailstone( n ) = n # hailstone( if 2|n then n/2 else n*3 + 1 )

if _name_ == '-main-'
  h27 = hailstone( 27 )
  assert( h27.length() == 112 and h27.startsWith([27, 82, 41, 124]) and h27.endsWith([8, 4, 2, 1]) )

  val (n, len) = maxBy( snd, [(i, hailstone( i ).length()) | i <- 1:100000] )

  println( n, len )


fun hailstone_step(x: int): int =
  if (x % 2) == 0
  then x/2
  else (3*x) + 1

fun hailstone_seq(x: int): []int =
  let capacity = 100
  let i = 1
  let steps = replicate capacity (-1)
  let steps[0] = x
  loop ((capacity,i,steps,x)) = while x != 1 do
    let (steps, capacity) =
      if i == capacity then
        (concat steps (replicate capacity (-1)),
         capacity * 2)
      else (steps, capacity)
    let x = hailstone_step x
    let steps[i] = x
    in (capacity, i+1, steps, x)
  in #1 (split i steps)

fun hailstone_len(x: int): int =
  let i = 1
  loop ((i,x)) = while x != 1 do
    (i+1, hailstone_step x)
  in i

fun max (x: int) (y: int): int = if x < y then y else x

fun main (x: int) (n: int): ([]int, int) =
  (hailstone_seq x,
   reduce max 0 (map hailstone_len (map (1+) (iota (n-1)))))


package main

import "fmt"

// 1st arg is the number to generate the sequence for.
// 2nd arg is a slice to recycle, to reduce garbage.
func hs(n int, recycle []int) []int {
    s := append(recycle[:0], n)
    for n > 1 {
        if n&1 == 0 {
            n = n / 2
        } else {
            n = 3*n + 1
        }
        s = append(s, n)
    }
    return s
}

func main() {
    seq := hs(27, nil)
    fmt.Printf("hs(27): %d elements: [%d %d %d %d ... %d %d %d %d]\n",
        len(seq), seq[0], seq[1], seq[2], seq[3],
        seq[len(seq)-4], seq[len(seq)-3], seq[len(seq)-2], seq[len(seq)-1])

    var maxN, maxLen int
    for n := 1; n < 100000; n++ {
        seq = hs(n, seq)
        if len(seq) > maxLen {
            maxN = n
            maxLen = len(seq)
        }
    }
    fmt.Printf("hs(%d): %d elements\n", maxN, maxLen)
}


def hailstone = { long start ->
    def sequence = []
    while (start != 1) {
        sequence << start
        start = (start % 2l == 0l) ? start / 2l : 3l * start + 1l
    }
    sequence << start
}


import Data.List (maximumBy)
import Data.Ord (comparing)

-------------------- HAILSTONE SEQUENCE ------------------

collatz :: Int -> Int
collatz n
  | even n = n `div` 2
  | otherwise = 1 + 3 * n

hailstone :: Int -> [Int]
hailstone = takeWhile (1 /=) . iterate collatz

longestChain :: Int
longestChain =
  fst $
    maximumBy (comparing snd) $
      (,) <*> (length . hailstone) <$> [1 .. 100000]

--------------------------- TEST -------------------------
main :: IO ()
main =
  mapM_
    putStrLn
    [ "Collatz sequence for 27: ",
      (show . hailstone) 27,
      "The number " <> show longestChain,
      "has the longest hailstone sequence",
      "for any number less then 100000. ",
      "The sequence has length: "
        <> (show . length . hailstone $ longestChain)
    ]


DIMENSION stones(1000)

H27 = hailstone(27)
ALIAS(stones,1, first4,4)
ALIAS(stones,H27-3,  last4,4)
WRITE(ClipBoard, Name) H27, first4, "...", last4

longest_sequence = 0
DO try = 1, 1E5
  elements = hailstone(try)
  IF(elements >= longest_sequence) THEN
      number = try
      longest_sequence = elements
      WRITE(StatusBar, Name) number, longest_sequence
  ENDIF
ENDDO
WRITE(ClipBoard, Name) number, longest_sequence
END

FUNCTION hailstone( n )
   USE : stones

   stones(1) = n
   DO i = 1, LEN(stones)
     IF(stones(i) == 1) THEN
         hailstone = i
         RETURN
     ELSEIF( MOD(stones(i),2) ) THEN
       stones(i+1) = 3*stones(i) + 1
     ELSE
       stones(i+1) = stones(i) / 2
     ENDIF
   ENDDO
END


procedure hailstone(n)
    while n > 1 do {
        suspend n
        n := if n%2 = 0 then n/2 else 3*n+1
        }
    suspend 1
end


Home is a room.

To decide which list of numbers is the hailstone sequence for (N - number):
	let result be a list of numbers;
	add N to result;
	while N is not 1:
		if N is even, let N be N / 2;
		otherwise let N be (3 * N) + 1;
		add N to result;
	decide on result.

Hailstone length cache relates various numbers to one number.

To decide which number is the hailstone sequence length for (N - number):
	let ON be N;
	let length so far be 0;
	while N is not 1:
		if N relates to a number by the hailstone length cache relation:
			let result be length so far plus the number to which N relates by the hailstone length cache relation;
			now the hailstone length cache relation relates ON to result;
			decide on result;
		if N is even, let N be N / 2;
		otherwise let N be (3 * N) + 1;
		increment length so far;
	let result be length so far plus 1;
	now the hailstone length cache relation relates ON to result;
	decide on result.

To say first and last (N - number) entry/entries in (L - list of values of kind K):
	let length be the number of entries in L;
	if length <= N * 2:
		say L;
	else:
		repeat with M running from 1 to N:
			if M > 1, say ", ";
			say entry M in L;
		say " ... ";
		repeat with M running from length - N + 1 to length:
			say entry M in L;
			if M < length, say ", ".

When play begins:
	let H27 be the hailstone sequence for 27;
	say "Hailstone sequence for 27 has [number of entries in H27] element[s]: [first and last 4 entries in H27].";
	let best length be 0;
	let best number be 0;
	repeat with N running from 1 to 99999:
		let L be the hailstone sequence length for N;
		if L > best length:
			let best length be L;
			let best number be N;
	say "The number under 100,000 with the longest hailstone sequence is [best number] with [best length] element[s].";
	end the story.


makeItHail := method(n,
  stones := list(n)
  while (n != 1,
    if(n isEven,
      n = n / 2,
      n = 3 * n + 1
    )
    stones append(n)
  )
  stones
)

out := makeItHail(27)
writeln("For the sequence beginning at 27, the number of elements generated is ", out size, ".")
write("The first four elements generated are ")
for(i, 0, 3,
  write(out at(i), " ")
)
writeln(".")

write("The last four elements generated are ")
for(i, out size - 4, out size - 1,
  write(out at(i), " ")
)
writeln(".")

numOfElems := 0
nn := 3
for(x, 3, 100000,
  out = makeItHail(x)
  if(out size > numOfElems,
    numOfElems = out size
    nn = x
  )
)

writeln("For numbers less than or equal to 100,000, ", nn,
" has the longest sequence of ", numOfElems, " elements.")


collatz = method(n,
  n println
  unless(n <= 1,
    if(n even?, collatz(n / 2), collatz(n * 3 + 1)))
)


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

class Hailstone {

  public static List<Long> getHailstoneSequence(long n) {
    if (n <= 0)
      throw new IllegalArgumentException("Invalid starting sequence number");
    List<Long> list = new ArrayList<Long>();
    list.add(Long.valueOf(n));
    while (n != 1) {
      if ((n & 1) == 0)
        n = n / 2;
      else
        n = 3 * n + 1;
      list.add(Long.valueOf(n));
    }
    return list;
  }

  public static void main(String[] args) {
    List<Long> sequence27 = getHailstoneSequence(27);
    System.out.println("Sequence for 27 has " + sequence27.size() + " elements: " + sequence27);

    long MAX = 100000;
    // Simple way
    {
      long highestNumber = 1;
      int highestCount = 1;
      for (long i = 2; i < MAX; i++) {
        int count = getHailstoneSequence(i).size();
        if (count > highestCount) {
          highestCount = count;
          highestNumber = i;
        }
      }
      System.out.println("Method 1, number " + highestNumber + " has the longest sequence, with a length of " + highestCount);
    }

    // More memory efficient way
    {
      long highestNumber = 1;
      int highestCount = 1;
      for (long i = 2; i < MAX; i++) {
        int count = 1;
        long n = i;
        while (n != 1) {
          if ((n & 1) == 0)
            n = n / 2;
          else
            n = 3 * n + 1;
          count++;
        }
        if (count > highestCount) {
          highestCount = count;
          highestNumber = i;
        }
      }
      System.out.println("Method 2, number " + highestNumber + " has the longest sequence, with a length of " + highestCount);
    }

    // Efficient for analyzing all sequences
    {
      long highestNumber = 1;
      long highestCount = 1;
      Map<Long, Integer> sequenceMap = new HashMap<Long, Integer>();
      sequenceMap.put(Long.valueOf(1), Integer.valueOf(1));

      List<Long> currentList = new ArrayList<Long>();
      for (long i = 2; i < MAX; i++) {
        currentList.clear();
        Long n = Long.valueOf(i);
        Integer count = null;
        while ((count = sequenceMap.get(n)) == null) {
          currentList.add(n);
          long nValue = n.longValue();
          if ((nValue & 1) == 0)
            n = Long.valueOf(nValue / 2);
          else
            n = Long.valueOf(3 * nValue + 1);
        }
        int curCount = count.intValue();
        for (int j = currentList.size() - 1; j >= 0; j--)
          sequenceMap.put(currentList.get(j), Integer.valueOf(++curCount));
        if (curCount > highestCount) {
          highestCount = curCount;
          highestNumber = i;
        }
      }
      System.out.println("Method 3, number " + highestNumber + " has the longest sequence, with a length of " + highestCount);
    }
    return;
  }
}


function hailstone (n) {
    var seq = [n];
    while (n > 1) {
        n = n % 2 ? 3 * n + 1 : n / 2;
        seq.push(n);
    }
    return seq;
}

// task 2: verify the sequence for n = 27
var h = hailstone(27), hLen = h.length;
print("sequence 27 is (" + h.slice(0, 4).join(", ") + " ... "
    + h.slice(hLen - 4, hLen).join(", ") + "). length: " + hLen);

// task 3: find the longest sequence for n < 100000
for (var n, max = 0, i = 100000; --i;) {
    var seq = hailstone(i), sLen = seq.length;
    if (sLen > max) {
        n = i;
        max = sLen;
    }
}
print("longest sequence: " + max + " numbers for starting point " + n);


# Generate the hailstone sequence as a stream to save space (and time) when counting
def hailstone:
  recurse( if . > 1 then
              if . % 2 == 0 then ./2|floor else 3*. + 1 end
           else empty
           end );

def count(g): reduce g as $i (0; .+1);

# return [i, length] for the first maximal-length hailstone sequence where i is in [1 .. n]
def max_hailstone(n):
  # state: [i, length]
  reduce range(1; n+1) as $i
    ([0,0];
     ($i | count(hailstone)) as $l
     | if $l > .[1] then [$i, $l] else . end);


function hailstonelength(n::Integer)
    len = 1
    while n > 1
        n = ifelse(iseven(n), n ÷ 2, 3n + 1)
        len += 1
    end
    return len
end

@show hailstonelength(27); nothing
@show findmax([hailstonelength(i) for i in 1:100_000]); nothing


import java.util.ArrayDeque

fun hailstone(n: Int): ArrayDeque<Int> {
    val hails = when {
        n == 1 -> ArrayDeque<Int>()
        n % 2 == 0 -> hailstone(n / 2)
        else -> hailstone(3 * n + 1)
    }
    hails.addFirst(n)
    return hails
}

fun main(args: Array<String>) {
    val hail27 = hailstone(27)
    fun showSeq(s: List<Int>) = s.map { it.toString() }.reduce { a, b -> a + ", " + b }
    println("Hailstone sequence for 27 is " + showSeq(hail27.take(3)) + " ... "
            + showSeq(hail27.drop(hail27.size - 3)) + " with length ${hail27.size}.")

    var longestHail = hailstone(1)
    for (x in 1..99999)
        longestHail = arrayOf(hailstone(x), longestHail).maxBy { it.size } ?: longestHail
    println("${longestHail.first} is the number less than 100000 with " +
            "the longest sequence, having length ${longestHail.size}.")
}


[
	define_tag("hailstone", -required="n", -type="integer", -copy);
		local("sequence") = array(#n);
		while(#n != 1);
			((#n % 2) == 0) ? #n = (#n / 2) | #n = (#n * 3 + 1);
			#sequence->insert(#n);
		/while;
		return(#sequence);
	/define_tag;

	local("result");
	#result = hailstone(27);
	while(#result->size > 8);
		#result->remove(5);
	/while;
	#result->insert("...",5);

	"Hailstone sequence for n = 27 -> { " + #result->join(", ") + " }";

	local("longest_sequence") = 0;
	local("longest_index") = 0;
	loop(-from=1, -to=100000);
		local("length") = hailstone(loop_count)->size;
		if(#length > #longest_sequence);
			#longest_index = loop_count;
			#longest_sequence = #length;
		/if;
	/loop;

	"<br/>";
	"Number with the longest sequence under 100,000: " #longest_index + ", with " + #longest_sequence + " elements.";
]


implement Hailstone;

include "sys.m"; sys: Sys;
include "draw.m";

Hailstone: module {
	init: fn(ctxt: ref Draw->Context, args: list of string);
};

init(nil: ref Draw->Context, nil: list of string)
{
	sys = load Sys Sys->PATH;

	seq := hailstone(big 27);
	l := len seq;

	sys->print("hailstone(27):  ");
	for(i := 0; i < 4; i++) {
		sys->print("%bd, ", hd seq);
		seq = tl seq;
	}
	sys->print("⋯");

	while(len seq > 4)
		seq = tl seq;

	while(seq != nil) {
		sys->print(", %bd", hd seq);
		seq = tl seq;
	}
	sys->print(" (length %d)\n", l);

	max := 1;
	maxn := big 1;
	for(n := big 2; n < big 100000; n++) {
		cur := len hailstone(n);
		if(cur > max) {
			max = cur;
			maxn = n;
		}
	}
	sys->print("hailstone(%bd) has length %d\n", maxn, max);
}

hailstone(i: big): list of big
{
	if(i == big 1)
		return big 1 :: nil;
	if(i % big 2 == big 0)
		return i :: hailstone(i / big 2);
	return i :: hailstone((big 3 * i) + big 1);
}


on hailstone (n, sequenceList)
  len = 1
  repeat while n<>1
    if listP(sequenceList) then sequenceList.add(n)
    if n mod 2 = 0 then
      n = n / 2
    else
      n = 3 * n + 1
    end if
    len = len + 1
  end repeat
  if listP(sequenceList) then sequenceList.add(n)
  return len
end


to hail.next :n
  output ifelse equal? 0 modulo :n 2 [:n/2] [3*:n + 1]
end

to hail.seq :n
  if :n = 1 [output [1]]
  output fput :n hail.seq hail.next :n
end

show hail.seq 27
show count hail.seq 27

to max.hail :n
  localmake "max.n 0
  localmake "max.length 0
  repeat :n [if greater? count hail.seq repcount  :max.length [
    make "max.n repcount
    make "max.length count hail.seq repcount
  ] ]
  (print :max.n [has hailstone sequence length] :max.length)
end

max.hail 100000


:- object(hailstone).

	:- public(generate_sequence/2).
	:- mode(generate_sequence(+natural, -list(natural)), zero_or_one).
	:- info(generate_sequence/2, [
		comment is 'Generates the Hailstone sequence that starts with its first argument. Fails if the argument is not a natural number.',
		argnames is ['Start', 'Sequence']
	]).

	:- public(write_sequence/1).
	:- mode(write_sequence(+natural), zero_or_one).
	:- info(write_sequence/1, [
		comment is 'Writes to the standard output the Hailstone sequence that starts with its argument. Fails if the argument is not a natural number.',
		argnames is ['Start']
	]).

	:- public(sequence_length/2).
	:- mode(sequence_length(+natural, -natural), zero_or_one).
	:- info(sequence_length/2, [
		comment is 'Calculates the length of the Hailstone sequence that starts with its first argument. Fails if the argument is not a natural number.',
		argnames is ['Start', 'Length']
	]).

	:- public(longest_sequence/4).
	:- mode(longest_sequence(+natural, +natural, -natural, -natural), zero_or_one).
	:- info(longest_sequence/4, [
		comment is 'Calculates the longest Hailstone sequence in the interval [Start, End]. Fails if the interval is not valid.',
		argnames is ['Start', 'End', 'N', 'Length']
	]).

	generate_sequence(Start, Sequence) :-
		integer(Start),
		Start >= 1,
		sequence(Start, Sequence).

	sequence(1, [1]) :-
		!.
	sequence(N, [N| Sequence]) :-
		(	N mod 2 =:= 0 ->
			M is N // 2
		;	M is (3 * N) + 1
		),
		sequence(M, Sequence).

	write_sequence(Start) :-
		integer(Start),
		Start >= 1,
		sequence(Start).

	sequence(1) :-
		!,
		write(1), nl.
	sequence(N) :-
		write(N), write(' '),
		(	N mod 2 =:= 0 ->
			M is N // 2
		;	M is (3 * N) + 1
		),
		sequence(M).

	sequence_length(Start, Length) :-
		integer(Start),
		Start >= 1,
		sequence_length(Start, 1, Length).

	sequence_length(1, Length, Length) :-
		!.
	sequence_length(N, Length0, Length) :-
		Length1 is Length0 + 1,
		(	N mod 2 =:= 0 ->
			M is N // 2
		;	M is (3 * N) + 1
		),
		sequence_length(M, Length1, Length).

	longest_sequence(Start, End, N, Length) :-
		integer(Start),
		integer(End),
		Start >= 1,
		Start =< End,
		longest_sequence(Start, End, 1, N, 1, Length).

	longest_sequence(Current, End, N, N, Length, Length) :-
		Current > End,
		!.
	longest_sequence(Current, End, N0, N, Length0, Length) :-
		sequence_length(Current, 1, CurrentLength),
		Next is Current + 1,
		(	CurrentLength > Length0 ->
			longest_sequence(Next, End, Current, N, CurrentLength, Length)
		;	longest_sequence(Next, End, N0, N, Length0, Length)
		).

:- end_object.


HAI 1.3

HOW IZ I hailin YR stone
    I HAS A sequence ITZ A BUKKIT
    sequence HAS A length ITZ 1
    sequence HAS A SRS 0 ITZ stone

    IM IN YR stoner
        BOTH SAEM stone AN 1, O RLY?
            YA RLY, FOUND YR sequence
        OIC

        MOD OF stone AN 2, O RLY?
            YA RLY, stone R SUM OF PRODUKT OF stone AN 3 AN 1
            NO WAI, stone R QUOSHUNT OF stone AN 2
        OIC

        sequence HAS A SRS sequence'Z length ITZ stone
        sequence'Z length R SUM OF sequence'Z length AN 1
    IM OUTTA YR stoner
IF U SAY SO

I HAS A hail27 ITZ I IZ hailin YR 27 MKAY
VISIBLE "hail(27) = "!

IM IN YR first4 UPPIN YR i TIL BOTH SAEM i AN 4
    VISIBLE hail27'Z SRS i " "!
IM OUTTA YR first4
VISIBLE "..."!

IM IN YR last4 UPPIN YR i TIL BOTH SAEM i AN 4
    VISIBLE " " hail27'Z SRS SUM OF 108 AN i!
IM OUTTA YR last4
VISIBLE ", length = " hail27'Z length

I HAS A max, I HAS A len ITZ 0

BTW, DIS IZ RLY NOT FAST SO WE ONLY CHEK N IN [75000, 80000)
IM IN YR maxer UPPIN YR n TIL BOTH SAEM n AN 5000
    I HAS A n ITZ SUM OF n AN 75000
    I HAS A seq ITZ I IZ hailin YR n MKAY
    BOTH SAEM len AN SMALLR OF len AN seq'Z length, O RLY?
        YA RLY, max R n, len R seq'Z length
    OIC
IM OUTTA YR maxer

VISIBLE "len(hail(" max ")) = " len

KTHXBYE


function hailstone( n, print_numbers )
    local n_iter = 1

    while n ~= 1 do
        if print_numbers then print( n ) end
        if n % 2 == 0 then
            n = n / 2
        else
            n = 3 * n + 1
        end

        n_iter = n_iter + 1
    end
    if print_numbers then print( n ) end

    return n_iter;
end

hailstone( 27, true )

max_i, max_iter = 0, 0
for i = 1, 100000 do
    num = hailstone( i, false )
    if num >= max_iter then
        max_i = i
        max_iter = num
    end
end

print( string.format( "Needed %d iterations for the number %d.\n", max_iter, max_i ) )


Module hailstone.Task {
      hailstone=lambda  (n as long)->{
            =lambda n  (&val) ->{
                  if n=1 then =false: exit
                  =true
                  if n mod 2=0 then n/=2 : val=n: exit
                  n*=3 : n++: val=n
            }
      }
      Count=Lambda (n) ->{
            m=lambda n ->{
                  if n=1 then =false: exit
                  =true :if n mod 2=0 then n/=2 :exit
                  n*=3 : n++
            }
            c=1
            While m() {c++}
            =c

      }
      k=Hailstone(27)
      counter=1
      x=0
      Print 27,
      While k(&x) {
            counter++
            Print x,
            if counter=4 then exit
      }
      Print
      Flush  ' empty current stack
      While k(&x) {
            counter++
            data x   ' send to end of stack -used as FIFO
            if stack.size>4 then drop
      }
      \\ [] return a stack object and leave empty current stack
      \\ Print use automatic iterator to print all values in columns.
      Print []
      Print "counter:";counter
      m=0
      For i=2 to 99999 {
            m1=max.data(count(i), m)
            if m1<>m then m=m1: im=i
      }
      Print Format$("Number {0} has then longest hailstone sequence of length {1}", im, m)
}
hailstone.Task


hailstone := proc( N )
    local n := N, HS := Array([n]);
    while n > 1 do
        if type(n,even) then
            n := n/2;
        else
            n := 3*n+1;
        end if;
        HS(numelems(HS)+1) := n;
    end do;
    HS;
end proc;


HailstoneF[n_] := NestWhileList[If[OddQ[#], 3 # + 1, #/2] &, n, # > 1 &]


function x = hailstone(n)
  x = n;
  while n > 1
       % faster than mod(n, 2)
    if n ~= floor(n / 2) * 2
      n = n * 3 + 1;
    else
      n = n / 2;
    end
    x(end + 1) = n; %#ok
  end


collatz(n) := block([L], L: [n], while n > 1 do
(n: if evenp(n) then n/2 else 3*n + 1, L: endcons(n, L)), L)$

collatz_length(n) := block([m], m: 1, while n > 1 do
(n: if evenp(n) then n/2 else 3*n + 1, m: m + 1), m)$

collatz_max(n) := block([j, m, p], m: 0,
for i from 1 thru n do
   (p: collatz_length(i), if p > m then (m: p, j: i)),
[j, m])$

collatz(27);           /* [27, 82, 41, ..., 4, 2, 1] */
length(%);             /* 112 */
collatz_length(27);    /* 112 */
collatz_max(100000);   /* [77031, 351] */


:- module hailstone.

:- interface.

:- import_module int, list.

:- func hailstone(int) = list(int).
:- pred hailstone(int::in, list(int)::out) is det.

:- implementation.

hailstone(N) = S :- hailstone(N, S).

hailstone(N, [N|S]) :-
  ( N = 1 ->       S = []
  ; N mod 2 = 0 -> hailstone(N/2, S)
  ;                hailstone(3 * N + 1, S) ).

:- end_module hailstone.


fun hail (x = 1) = [1]
       | (x rem 2 = 0) = x :: hail (x div 2)
       | x = x :: hail (x * 3 + 1)

fun hailstorm
		([], i, largest, largest_at) = (largest_at, largest)
	| 	(x :: xs, i, largest, largest_at) =
		let
			val k = len (hail x)
		in
			if k > largest then
				hailstorm (xs, i + 1, k, i)
			else
				hailstorm (xs, i + 1, largest, largest_at)
			end
	| 	(x :: xs) = hailstorm (x :: xs, 1, 0, 0)

 ;

val h27 = hail 27;
print "hailstone sequence for the number 27 has ";
print ` len (h27);
print " elements starting with ";
print ` sub (h27, 0, 4);
print " and ending with ";
print ` sub (h27, len(h27)-4, len h27);
println ".";

val biggest = hailstorm ` iota (100000 - 1);

print "The number less than 100,000 which has the longest ";
print "hailstone sequence is at element ";
print ` ref (biggest, 0);
print " and is of length ";
println ` ref (biggest, 1);


MODULE hailst;

IMPORT  InOut;

CONST   maxCard         = MAX (CARDINAL) DIV 3;
TYPE    action          = (List, Count, Max);
VAR     a               : CARDINAL;

PROCEDURE HailStone (start  : CARDINAL;  type  : action) : CARDINAL;

VAR     n, max, count           : CARDINAL;

BEGIN
  count := 1;
  n := start;
  max := n;
  LOOP
    IF  type = List  THEN
      InOut.WriteCard (n, 12);
      IF  count MOD 6 = 0  THEN  InOut.WriteLn  END
    END;
    IF  n = 1  THEN  EXIT  END;
    IF  ODD (n)  THEN
      IF  n < maxCard  THEN
        n := 3 * n + 1;
        IF   n > max  THEN  max := n  END
      ELSE
        InOut.WriteString ("Exceeding max value for type CARDINAL at count = ");
        InOut.WriteCard (count, 10);
        InOut.WriteString (" for intermediate value ");
        InOut.WriteCard (n, 10);
        InOut.WriteString (". Aborting.");
        HALT
      END
    ELSE
      n := n DIV 2
    END;
    INC (count)
  END;
  IF  type = Max  THEN  RETURN  max  ELSE  RETURN  count  END
END HailStone;

PROCEDURE FindMax (num   : CARDINAL);

VAR     val, maxCount, maxVal, cnt      : CARDINAL;

BEGIN
  maxCount := 0;
  maxVal := 0;
  FOR  val := 2 TO num  DO
   cnt := HailStone (val, Count);
    IF  cnt > maxCount  THEN
      maxVal := val;
      maxCount := cnt
    END
  END;
  InOut.WriteString ("Longest sequence below ");        InOut.WriteCard (num, 1);
  InOut.WriteString (" is ");           InOut.WriteCard (HailStone (maxVal, Count), 1);
  InOut.WriteString (" for n = ");      InOut.WriteCard (maxVal, 1);
  InOut.WriteString (" with an intermediate maximum of ");
  InOut.WriteCard (HailStone (maxVal, Max), 1);
  InOut.WriteLn
END FindMax;

BEGIN
  a := HailStone (27, List);
  InOut.WriteLn;
  InOut.WriteString ("Iterations total = ");    InOut.WriteCard (HailStone (27, Count), 12);
  InOut.WriteString (" max value = ");          InOut.WriteCard (HailStone (27, Max)  , 12);
  InOut.WriteLn;
  FindMax (100000);
  InOut.WriteString ("Done.");          InOut.WriteLn
END hailst.


def hailstone(n)
	seq = list()

	while (n > 1)
		append seq n
		if (n % 2)=0
			n = int(n / 2)
		else
			n = int((3 * n) + 1)
		end
	end
	append seq n
	return seq
end

h = hailstone(27)
println "hailstone(27)"
println "total elements: " + len(hailstone(27))
print   h[0] + ", " + h[1] + ", " + h[2] + ", " + h[3] + ", ..., "
println h[-4] + ", " + h[-3] + ", " + h[-2] + ", " + h[-1]

max = 0
maxLoc = 0
for i in range(1,99999)
	result = len(hailstone(i))
	if (result > max)
		max = result
		maxLoc = i
	end
end
print   "\nThe number less than 100,000 with the longest sequence is "
println maxLoc + " with a length of " + max


/* NetRexx */

options replace format comments java crossref savelog symbols binary

do
  start = 27
  hs = hailstone(start)
  hsCount = hs.words
  say 'The number' start 'has a hailstone sequence comprising' hsCount 'elements'
  say '  its first four elements are:' hs.subword(1, 4)
  say '   and last four elements are:' hs.subword(hsCount - 3)

  hsMax = 0
  hsCountMax = 0
  llimit = 100000
  loop x_ = 1 to llimit - 1
    hs = hailstone(x_)
    hsCount = hs.words
    if hsCount > hsCountMax then do
      hsMax = x_
      hsCountMax = hsCount
      end
    end x_

  say 'The number' hsMax 'has the longest hailstone sequence in the range 1 to' llimit - 1 'with a sequence length of' hsCountMax
catch ex = Exception
  ex.printStackTrace
end

return

method hailstone(hn = long) public static returns Rexx signals IllegalArgumentException

  hs = Rexx('')
  if hn <= 0 then signal IllegalArgumentException('Invalid start point.  Must be a positive integer greater than 0')

  loop label n_ while hn > 1
    hs = hs' 'hn
    if hn // 2 \= 0 then hn = hn * 3 + 1
                    else hn = hn % 2
    end n_
  hs = hs' 'hn

  return hs.strip


proc hailstone(n: int): seq[int] =
  result = @[n]
  var n = n
  while n > 1:
    if (n and 1) == 1:
      n = 3 * n + 1
    else:
      n = n div 2
    result.add n

when isMainModule:
  import strformat, strutils
  let h = hailstone(27)
  echo &"Hailstone sequence for number 27 has {h.len} elements."
  let first = h[0..3].join(", ")
  let last = h[^4..^1].join(", ")
  echo &"This sequence begins with {first} and ends with {last}."

  var m, mi = 0
  for i in 1..<100_000:
    let n = hailstone(i).len
    if n > m:
      m = n
      mi = i
  echo &"\nFor numbers < 100_000, maximum length {m} was found for Hailstone({mi})."


MODULE hailst;

IMPORT  Out;

CONST   maxCard         = MAX (INTEGER) DIV 3;
        List            = 1;
        Count           = 2;
        Max             = 3;

VAR     a               : INTEGER;

PROCEDURE HailStone (start, type  : INTEGER) : INTEGER;

VAR     n, max, count           : INTEGER;

BEGIN
  count := 1;
  n := start;
  max := n;
  LOOP
    IF  type = List  THEN
      Out.Int (n, 12);
      IF  count MOD 6 = 0  THEN  Out.Ln  END
    END;
    IF  n = 1  THEN  EXIT  END;
    IF  ODD (n)  THEN
      IF  n < maxCard  THEN
        n := 3 * n + 1;
        IF   n > max  THEN  max := n  END
      ELSE
        Out.String ("Exceeding max value for type INTEGER at: ");
        Out.String (" n = ");           Out.Int (start, 12);
        Out.String (" , count = ");     Out.Int (count, 12);
        Out.String (" and intermediate value ");
        Out.Int (n, 1);
        Out.String (". Aborting.");
        Out.Ln;
        HALT (2)
      END
    ELSE
      n := n DIV 2
    END;
    INC (count)
  END;
  IF  type = Max  THEN  RETURN  max  ELSE  RETURN  count  END
END HailStone;

PROCEDURE FindMax (num   : INTEGER);

VAR     val, maxCount, maxVal, cnt      : INTEGER;

BEGIN
  maxCount := 0;
  maxVal := 0;
  FOR  val := 2 TO num  DO
   cnt := HailStone (val, Count);
    IF  cnt > maxCount  THEN
      maxVal := val;
      maxCount := cnt
    END
  END;
  Out.String ("Longest sequence below ");       Out.Int (num, 1);
  Out.String (" is ");                          Out.Int (HailStone (maxVal, Count), 1);
  Out.String (" for n = ");                     Out.Int (maxVal, 1);
  Out.String (" with an intermediate maximum of ");
  Out.Int (HailStone (maxVal, Max), 1);
  Out.Ln
END FindMax;

BEGIN
  a := HailStone (27, List);
  Out.Ln;
  Out.String ("Iterations total = ");   Out.Int (HailStone (27, Count), 12);
  Out.String (" max value = ");         Out.Int (HailStone (27, Max)  , 12);
  Out.Ln;
  FindMax (1000000);
  Out.String ("Done.");
  Out.Ln
END hailst.


: hailstone   // n -- [n]
| l |
   ListBuffer new ->l
   while(dup 1 <>) [ dup l add dup isEven ifTrue: [ 2 / ] else: [ 3 * 1+ ] ]
   l add l dup freeze ;

hailstone(27) dup size println dup left(4) println right(4) println
100000 seq map(#[ dup hailstone size swap Pair new ]) reduce(#maxKey) println


sequence = hailstone(27)
say "Hailstone sequence for 27 has" sequence~items "elements and is ["sequence~toString('l', ", ")"]"

highestNumber = 1
highestCount = 1

loop i = 2 to 100000
    sequence = hailstone(i)
    count = sequence~items
    if count > highestCount then do
        highestNumber = i
        highestCount = count
    end
end
say "Number" highestNumber "has the longest sequence with" highestCount "elements"

-- short routine to generate a hailstone sequence
::routine hailstone
  use arg n

  sequence = .array~of(n)
  loop while n \= 1
      if n // 2 == 0 then n = n / 2
      else n = 3 * n + 1
      sequence~append(n)
  end
  return sequence


#include <order/interpreter.h>

#define ORDER_PP_DEF_8hailstone ORDER_PP_FN(                  \
8fn(8N,                                                       \
    8cond((8equal(8N, 1), 8seq(1))                            \
          (8is_0(8remainder(8N, 2)),                          \
           8seq_push_front(8N, 8hailstone(8quotient(8N, 2)))) \
          (8else,                                             \
           8seq_push_front(8N, 8hailstone(8inc(8times(8N, 3))))))) )

ORDER_PP(
  8lets((8H, 8seq_map(8to_lit, 8hailstone(27)))
        (8S, 8seq_size(8H)),
        8print(8(h(27) - length:) 8to_lit(8S) 8comma 8space
               8(starts with:) 8seq_take(4, 8H) 8comma 8space
               8(ends with:) 8seq_drop(8minus(8S, 4), 8H))
        ) )


declare
  fun {HailstoneSeq N}
     N > 0 = true %% assert
     if N == 1 then         [1]
     elseif {IsEven N} then N|{HailstoneSeq N div 2}
     else                   N|{HailstoneSeq 3*N+1}
     end
  end

  HSeq27 = {HailstoneSeq 27}
  {Length HSeq27} = 112
  {List.take HSeq27 4} = [27 82 41 124]
  {List.drop HSeq27 108} = [8 4 2 1]

  fun {MaxBy2nd A=A1#A2 B=B1#B2}
     if B2 > A2 then B else A end
  end

  Pairs = {Map {List.number 1 99999 1}
           fun {$ I} I#{Length {HailstoneSeq I}} end}

  MaxI#MaxLen = {List.foldL Pairs MaxBy2nd 0#0}
  {System.showInfo
   "Maximum length "#MaxLen#" was found for hailstone("#MaxI#")"}


program ShowHailstoneSequence;
{$IFDEF FPC}
  {$MODE delphi} //or objfpc
{$Else}
  {$Apptype Console} // for delphi
{$ENDIF}
uses
  SysUtils;// format
const
  maxN = 10*1000*1000;// for output 1000*1000*1000

type
  tiaArr = array[0..1000] of Uint64;
  tIntArr = record
               iaMaxPos : integer;
               iaArr    : tiaArr
            end;
  tpiaArr = ^tiaArr;

function HailstoneSeqCnt(n: UInt64): NativeInt;
begin
  result := 0;
  //ensure n to be odd
  while not(ODD(n)) do
  Begin
    inc(result);
    n := n shr 1;
  end;

  IF n > 1 then
  repeat
    //now n == odd -> so two steps in one can be made
    repeat
      n := (3*n+1) SHR 1;inc(result,2);
    until NOT(Odd(n));
    //now n == even -> so only one step can be made
    repeat
      n := n shr 1;      inc(result);
    until odd(n);
  until n = 1;
end;

procedure GetHailstoneSequence(aStartingNumber: NativeUint;var aHailstoneList: tIntArr);
var
  maxPos: NativeInt;
  n: UInt64;
  pArr : tpiaArr;
begin
  with aHailstoneList do
  begin
    maxPos := 0;
    pArr := @iaArr;
  end;
  n  := aStartingNumber;
  pArr^[maxPos] := n;
  while n <> 1 do
  begin
    if odd(n) then
      n := (3*n+1)
    else
      n := n shr 1;
    inc(maxPos);
    pArr^[maxPos] := n;
  end;
  aHailstoneList.iaMaxPos  := maxPos;
end;

var
  i,Limit: NativeInt;
  lList: tIntArr;
  lAverageLength:Uint64;
  lMaxSequence: NativeInt;
  lMaxLength,lgth: NativeInt;
begin
  lList.iaMaxPos := 0;
  GetHailstoneSequence(27, lList);//319804831
  with lList do
  begin
    Limit := iaMaxPos;
    writeln(Format('sequence of %d has %d  elements',[iaArr[0],Limit+1]));
    write(iaArr[0],',',iaArr[1],',',iaArr[2],',',iaArr[3],'..');
    For i := iaMaxPos-3 to iaMaxPos-1 do
       write(iaArr[i],',');
    writeln(iaArr[iaMaxPos]);
  end;
  Writeln;

  lMaxSequence := 0;
  lMaxLength := 0;
  i := 1;
  limit := 10*i;
  writeln(' Limit      : number with max length | average length');
  repeat
    lAverageLength:= 0;
    repeat
      lgth:= HailstoneSeqCnt(i);
      inc(lAverageLength, lgth);
      if lgth >= lMaxLength then
      begin
        lMaxSequence := i;
        lMaxLength := lgth+1;
      end;
      inc(i);
    until i = Limit;
    Writeln(Format(' %10d : %9d    |  %4d   |      %7.3f',
                   [limit,lMaxSequence, lMaxLength,0.9*lAverageLength/Limit]));
    limit := limit*10;
  until Limit > maxN;
end.


#!/usr/bin/perl

use warnings;
use strict;

my @h = hailstone(27);
print "Length of hailstone(27) = " . scalar @h . "\n";
print "[" . join(", ", @h[0 .. 3], "...", @h[-4 .. -1]) . "]\n";

my ($max, $n) = (0, 0);
for my $x (1 .. 99_999) {
    @h = hailstone($x);
    if (scalar @h > $max) {
        ($max, $n) = (scalar @h, $x);
    }
}

print "Max length $max was found for hailstone($n) for numbers < 100_000\n";

sub hailstone {
    my ($n) = @_;

    my @sequence = ($n);

    while ($n > 1) {
        if ($n % 2 == 0) {
            $n = int($n / 2);
        } else {
            $n = $n * 3 + 1;
        }

        push @sequence, $n;
    }

    return @sequence;
}


with javascript_semantics
function hailstone(atom n)
    sequence s = {n}
    while n!=1 do
        if remainder(n,2)=0 then
            n /= 2
        else
            n = 3*n+1
        end if
        s &= n
    end while
    return s
end function

function hailstone_count(atom n)
    integer count = 1
    while n!=1 do
        if remainder(n,2)=0 then
            n /= 2
        else
            n = 3*n+1
        end if
        count += 1
    end while
    return count
end function

sequence s = hailstone(27)
printf(1,"hailstone(27) = %v\n",{shorten(s,"numbers",4)})

integer hmax = 1, imax = 1,count
for i=2 to 1e5-1 do
    count = hailstone_count(i)
    if count>hmax then
        hmax = count
        imax = i
    end if
end for

printf(1,"The longest hailstone sequence under 100,000 is %d with %d elements.\n",{imax,hmax})


function hailstone($n,$seq=array()){
	$sequence = $seq;
	$sequence[] = $n;
	if($n == 1){
		return $sequence;
	}else{
		$n = ($n%2==0) ? $n/2 : (3*$n)+1;
		return hailstone($n, $sequence);
	}
}

$result = hailstone(27);
echo count($result) . ' Elements.
';
echo 'Starting with : ' . implode(",",array_slice($result,0,4)) .' and ending with : ' . implode(",",array_slice($result,count($result)-4)) . '
';

$maxResult = array(0);

for($i=1;$i<=100000;$i++){
		$result = count(hailstone($i));
		if($result > max($maxResult)){
			$maxResult = array($i=>$result);
		}
}
foreach($maxResult as $key => $val){
echo 'Number < 100000 with longest Hailstone seq.: ' . $key . ' with length of ' . $val;
}


import util.

go =>
   println("H27:"),
   H27 = hailstoneseq(27),
   H27Len = H27.len,
   println(len=H27.len),
   println(take(H27,4)++['...']++drop(H27,H27Len-4)),
   nl,

   println("Longest sequence < 100_000:"),
   longest_seq(99_999),

   nl.

% The Hailstone value of a number
hailstone(N) = N // 2, N mod 2 == 0 => true.
hailstone(N) = 3*N+1, N mod 2 == 1 => true.

% Sequence for a number
hailstoneseq(N) = Seq =>
   Seq := [N],
   while (N > 1)
      N := hailstone(N),
      Seq := Seq ++ [N]
   end.

%
% Use a map to cache the lengths.
% Here we don't care about the actual sequence.
%
longest_seq(Limit) =>
   Lens = new_map(), % caching the lengths
   MaxLen = 0,
   MaxN = 1,

   foreach(N in 1..Limit-1)
      M = N,
      CLen = 1,
      while (M > 1)
         if Lens.has_key(M) then
            CLen := CLen + Lens.get(M) - 1,
            M := 1
         else
            M := hailstone(M), % call the
            CLen := CLen + 1
         end
      end,
      Lens.put(N, CLen),
      if CLen > MaxLen then
         MaxLen := CLen,
         MaxN := N
      end
   end,
   println([maxLen=MaxLen, maxN=MaxN]),
   nl.


(de hailstone (N)
   (make
      (until (= 1 (link N))
         (setq N
            (if (bit? 1 N)
               (inc (* N 3))
               (/ N 2) ) ) ) ) )

(let L (hailstone 27)
   (println 27 (length L) (head 4 L) '- (tail 4 L)) )

(let N (maxi '((N) (length (hailstone N))) (range 1 100000))
   (println N (length (hailstone N))) )


#!/usr/bin/env pike

int next(int n)
{
    if (n==1)
        return 0;
    if (n%2)
        return 3*n+1;
    else
        return n/2;
}

array(int) hailstone(int n)
{
    array seq = ({ n });
    while (n=next(n))
        seq += ({ n });
    return seq;
}

void main()
{
    array(int) two = hailstone(27);
    if (equal(two[0..3], ({ 27, 82, 41, 124 })) && equal(two[<3..], ({ 8,4,2,1 })))
        write("sizeof(({ %{%d, %}, ... %{%d, %} }) == %d\n", two[0..3], two[<3..], sizeof(two));

    mapping longest = ([ "length":0, "start":0 ]);

    foreach(allocate(100000); int start; )
    {
        int length = sizeof(hailstone(start));
        if (length > longest->length)
        {
            longest->length = length;
            longest->start = start;
        }
    }
    write("longest sequence starting at %d has %d elements\n", longest->start, longest->length);
}


test: proc options (main);
   declare (longest, n) fixed (15);
   declare flag bit (1);
   declare (i, value) fixed (15);

   /* Task 1: */
   flag = '1'b;
   put skip list ('The sequence for 27 is');
   i = hailstones(27);

   /* Task 2: */
   flag = '0'b;
   longest = 0;
   do i = 1 to 99999;
      if longest < hailstones(i) then
         do; longest = hailstones(i); value = i; end;
   end;
   put skip edit (value, ' has the longest sequence of ', longest) (a);

hailstones: procedure (n) returns ( fixed (15));
   declare n fixed (15) nonassignable;
   declare (m, p) fixed (15);

   m = n;
   p = 1;
   if flag then put skip list (m);
   do p = 1 by 1 while (m > 1);
      if iand(m, 1) = 0 then
         m = m/2;
      else
         m = 3*m + 1;
      if flag then put skip list (m);
   end;
   if flag then put skip list ('The hailstone sequence has length' || p);
   return (p);
end hailstones;

end test;


\newif\ifprint
\newcount\itercount
\newcount\currentnum
\def\hailstone#1{\itercount=0 \currentnum=#1 \hailstoneaux}
\def\hailstoneaux{%
	\advance\itercount1
	\ifprint\number\currentnum\space\space\fi
	\ifnum\currentnum>1
		\ifodd\currentnum
			\multiply\currentnum3 \advance\currentnum1
		\else
			\divide\currentnum2
		\fi
		\expandafter\hailstoneaux
	\fi
}

\parindent=0pt
\printtrue\hailstone{27}
Length = \number\itercount
\bigbreak

\newcount\ii \ii=1
\printfalse
\def\lenmax{0}
\def\seed{0}
\loop
	\ifnum\ii<100000
		\hailstone\ii
		\ifnum\itercount>\lenmax\relax
			\edef\lenmax{\number\itercount}%
			\edef\seed{\number\ii}%
		\fi
		\advance\ii1
\repeat
Seed max = \seed, length = \lenmax
\bye


function Get-HailStone {
    param($n)

    switch($n) {
        1              {$n;return}
        {$n % 2 -eq 0} {$n; return Get-Hailstone ($n = $n / 2)}
        {$n % 2 -ne 0} {$n; return Get-Hailstone ($n = ($n * 3) +1)}
    }
}

function Get-HailStoneBelowLimit {
    param($UpperLimit)

    for ($i = 1; $i -lt $UpperLimit; $i++) {
        [pscustomobject]@{
            'Number' = $i
            'Count' = (Get-HailStone $i).count
        }
    }
}


hailstone(1,[1]) :- !.
hailstone(N,[N|S]) :- 0 is N mod 2, N1 is N / 2, hailstone(N1,S).
hailstone(N,[N|S]) :- 1 is N mod 2, N1 is (3 * N) + 1, hailstone(N1, S).


// 1. Create a routine to generate the hailstone sequence for a number.
type odd x::int = x mod 2;
type even x::int = ~odd x;
odd x = typep odd x;
even x = typep even x;

hailstone 1       = [1];
hailstone n::even = n:hailstone (n div 2);
hailstone n::odd  = n:hailstone (3*n + 1);

// 2. Use the routine to show that the hailstone sequence for the number 27
//    has 112 elements starting with 27, 82, 41, 124 and ending with 8, 4, 2, 1
n = 27;
hs = hailstone n;
l = # hs;
using system;

printf
    ("the hailstone sequence for the number %d has %d elements " +
     "starting with %s and ending with %s\n")
    (n, l, __str__ (hs!!(0..3)), __str__ ( hs!!((l-4)..l)));

// 3. Show the number less than 100,000 which has the longest hailstone
//    sequence together with that sequences length.
printf ("the number under 100,000 with the longest sequence is %d " +
        "with a sequence length of %d\n")
       (foldr (\ (a,b) (c,d) -> if (b > d) then (a,b) else (c,d))
             (0,0)
             (map (\ x -> (x, # hailstone x)) (1..100000)));


def hailstone(n):
    seq = [n]
    while n>1:
        n = 3*n + 1 if n & 1 else n//2
        seq.append(n)
    return seq

if __name__ == '__main__':
    h = hailstone(27)
    assert len(h)==112 and h[:4]==[27, 82, 41, 124] and h[-4:]==[8, 4, 2, 1]
    print("Maximum length %i was found for hailstone(%i) for numbers <100,000" %
          max((len(hailstone(i)), i) for i in range(1,100000)))


[ 1 & ]                                 is odd      ( n --> b )

[ []
  [ over join swap
    dup 1 > while
    dup odd iff
      [ 3 * 1 + ]
    else
      [ 2 / ]
    swap again ]
   drop ]                              is hailstone ( n --> [ )

 [ stack ]                             is longest   (   --> s )

 [ stack ]                             is length    (   --> s )

27 hailstone
say "The hailstone sequence for 27 has "
dup size echo say " elements." cr
say "It starts with"
dup 4 split drop witheach [ sp echo ]
say " and ends with"
-4 split nip witheach [ sp echo ]
say "." cr cr

0 longest put  0 length put
99999 times
  [ i^ 1+ hailstone size
    dup length share > if
      [ dup length replace
        i^ 1+ longest replace ]
    drop ]
longest take echo
say " has the longest sequence of any number less than 100000."
cr say "It is " length take echo say " elements long." cr


### PART 1:
makeHailstone <- function(n){
  hseq <- n
  while (hseq[length(hseq)] > 1){
    current.value <- hseq[length(hseq)]
    if (current.value %% 2 == 0){
      next.value <- current.value / 2
    } else {
      next.value <- (3 * current.value) + 1
    }
    hseq <- append(hseq, next.value)
  }
  return(list(hseq=hseq, seq.length=length(hseq)))
}

### PART 2:
twenty.seven <- makeHailstone(27)
twenty.seven$hseq
twenty.seven$seq.length

### PART 3:
max.length <- 0;  lower.bound <- 1;  upper.bound <- 100000

for (index in lower.bound:upper.bound){
  current.hseq <- makeHailstone(index)
  if (current.hseq$seq.length > max.length){
    max.length <- current.hseq$seq.length
    max.index  <- index
  }
}

cat("Between ", lower.bound, " and ", upper.bound, ", the input of ",
    max.index, " gives the longest hailstone sequence, which has length ",
    max.length, ". \n", sep="")


#lang racket

(define hailstone
  (let ([t (make-hasheq)])
    (hash-set! t 1 '(1))
    (λ(n) (hash-ref! t n
            (λ() (cons n (hailstone (if (even? n) (/ n 2) (+ (* 3 n) 1)))))))))

(define h27 (hailstone 27))
(printf "h(27) = ~s, ~s items\n"
        `(,@(take h27 4) ... ,@(take-right h27 4))
        (length h27))

(define N 100000)
(define longest
  (for/fold ([m #f]) ([i (in-range 1 (add1 N))])
    (define h (hailstone i))
    (if (and m (> (cdr m) (length h))) m (cons i (length h)))))
(printf "for x<=~s, ~s has the longest sequence with ~s items\n"
        N (car longest) (cdr longest))


sub hailstone($n) { $n, { $_ %% 2 ?? $_ div 2 !! $_ * 3 + 1 } ... 1 }

my @h = hailstone(27);
say "Length of hailstone(27) = {[email protected]}";
say ~@h;

my $m = max ( (1..99_999).race.map: { +hailstone($_) => $_ } );
say "Max length {$m.key} was found for hailstone({$m.value}) for numbers < 100_000";


hail: func [
	"Returns the hailstone sequence for n"
	n [integer!]
	/local seq
] [
	seq: copy reduce [n]
	while [n <> 1] [
		append seq n: either n % 2 == 0 [n / 2] [3 * n + 1]
	]
	seq
]

hs27: hail 27
print [
	"the hail sequence of 27 has length" length? hs27
	"and has the form " copy/part hs27 3 "..."
	back back back tail hs27
]

maxN: maxLen: 0
repeat n 99999 [
	if (len: length? hail n) > maxLen [
		maxN: n
		maxLen: len
	]
]

print [
	"the number less than 100000 with the longest hail sequence is"
	maxN "with length" maxLen
]


/*REXX program tests a  number  and also a  range for  hailstone  (Collatz)  sequences. */
numeric digits 20                                /*be able to handle gihugeic numbers.  */
parse arg x y .                                  /*get optional arguments from the C.L. */
if x=='' | x==","   then x=     27               /*No  1st  argument?  Then use default.*/
if y=='' | y==","   then y= 100000 - 1           /* "  2nd      "        "   "     "    */
$= hailstone(x)     /*▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒task 1▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒*/
say  x   ' has a hailstone sequence of '      words($)
say      '    and starts with: '              subword($, 1, 4)    " ∙∙∙"
say      '    and  ends  with:  ∙∙∙'          subword($, max(5, words($)-3))
if y==0  then exit  /*▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒task 2▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒*/
say
w= 0;         do j=1  for y;  call hailstone j   /*traipse through the range of numbers.*/
              if #hs<=w  then iterate            /*Not big 'nuff?   Then keep traipsing.*/
              bigJ= j;   w= #hs                  /*remember what # has biggest hailstone*/
              end   /*j*/
say '(between 1 ──►'   y") "       bigJ      ' has the longest hailstone sequence: '   w
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
hailstone: procedure expose #hs; parse arg n 1 s /*N and S: are set to the 1st argument.*/
                     do #hs=1   while  n\==1     /*keep loop while   N   isn't  unity.  */
                     if n//2  then n= n * 3  + 1 /*N is odd ?   Then calculate  3*n + 1 */
                              else n= n % 2      /*"  " even?   Then calculate  fast ÷  */
                     s= s n                      /* [↑]  %   is REXX integer division.  */
                     end   /*#hs*/               /* [↑]  append  N  to the sequence list*/
           return s                              /*return the  S  string to the invoker.*/


size = 27
aList = []
hailstone(size)

func hailstone n
     add(aList,n)
     while n != 1
           if n % 2 = 0  n = n / 2
           else n = 3 * n + 1 ok
           add(aList, n)
     end
     see "first 4 elements : "
     for i = 1 to 4
         see "" + aList[i]  + " "
     next
     see nl
     see "last 4 elements : "
     for i = len(aList) - 3 to len(aList)
         see "" + aList[i] + " "
     next


def hailstone n
  seq = [n]
  until n == 1
    n = (n.even?) ? (n / 2) : (3 * n + 1)
    seq << n
  end
  seq
end

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

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


fn hailstone(start : u32) -> Vec<u32> {
    let mut res = Vec::new();
    let mut next = start;

    res.push(start);

    while next != 1  {
        next = if next % 2 == 0 { next/2 } else { 3*next+1 };
        res.push(next);
    }
    res
}

fn main() {
    let test_num = 27;
    let test_hailseq = hailstone(test_num);

    println!("For {} number of elements is {} ", test_num, test_hailseq.len());

    let fst_slice = test_hailseq[0..4].iter()
                        .fold("".to_owned(), |acc, i| { acc + &*(i.to_string()).to_owned() + ", " });
    let last_slice = test_hailseq[test_hailseq.len()-4..].iter()
                        .fold("".to_owned(), |acc, i| { acc + &*(i.to_string()).to_owned() + ", " });

    println!("  hailstone starting with {} ending with {} ", fst_slice, last_slice);

    let max_range = 100000;
    let mut max_len = 0;
    let mut max_seed = 0;
    for i_seed in 1..max_range {
        let i_len = hailstone(i_seed).len();

        if i_len > max_len {
            max_len = i_len;
            max_seed = i_seed;
        }
    }
    println!("Longest sequence is {} element long for seed {}", max_len, max_seed);
}


% lst=1, return list of elements; lst=0 just return length
define hailstone(n, lst)
{
  variable l;
  if (lst) l = {n};
  else l = 1;

  while (n > 1) {
    if (n mod 2)
      n = 3 * n + 1;
    else
      n /= 2;
    if (lst)
      list_append(l, n);
    else
      l++;
    % if (prn) () = printf("%d, ", n);
  }
  % if (prn) () = printf("\n");
  return l;
}

variable har = list_to_array(hailstone(27, 1)), more = 0;
() = printf("Hailstone(27) has %d elements starting with:\n\t", length(har));

foreach $1 (har[[0:3]])
  () = printf("%d, ", $1);

() = printf("\nand ending with:\n\t");
foreach $1 (har[[length(har)-4:]]) {
  if (more) () = printf(", ");
  more = printf("%d", $1);
}

() = printf("\ncalculating...\r");
variable longest, longlen = 0, h;
_for $1 (2, 99999, 1) {
  $2 = hailstone($1, 0);
  if ($2 > longlen) {
    longest = $1;
    longlen = $2;
    () = printf("longest sequence started w/%d and had %d elements  \r", longest, longlen);
  }
}
() = printf("\n");


* Create a routine to generate the hailstone sequence for one number;
%macro gen_seq(n);
   data hailstone;
      array hs_seq(100000);
      n=&n;
      do until (n=1);
         seq_size + 1;
         hs_seq(seq_size) = n;
         if mod(n,2)=0 then n=n/2;
         else n=(3*n)+1;
      end;
	  seq_size + 1;
      hs_seq(seq_size)=n;
	  call symputx('seq_length',seq_size);
   run;

   proc sql;
      title "First and last elements of Hailstone Sequence for number &n";
	  select seq_size as sequence_length, hs_seq1, hs_seq2, hs_seq3, hs_seq4
			%do i=&seq_length-3 %to &seq_length;
				, hs_seq&i
			%end;
		from hailstone;
	quit;
%mend;

* Use the routine to output the first and last four numbers in the sequence for 27;
%gen_seq(27);

* Show the number less than 100,000 which has the longest hailstone sequence, and what that length is ;
%macro longest_hailstone(start_num, end_num);
	data hailstone_analysis;
	  do start=&start_num to &end_num;
	    n=start;
		length_of_sequence=1;
		do while (n>1);
		  length_of_sequence+1;
		  if mod(n,2)=0 then n=n/2;
		  else n=(3*n) + 1;
		end;
		output;
	  end;
	run;

	proc sort data=hailstone_analysis;
	  by descending length_of_sequence;
	run;

	proc print data=hailstone_analysis (obs=1) noobs;
	  title "Number from &start_num to &end_num with longest Hailstone sequence";
	  var start length_of_sequence;
	run;
%mend;
%longest_hailstone(1,99999);


comment
  Compute and display "hailstone" (i.e., Collatz) sequence
  for a given number and find the longest sequence in the
  range permitted by S-BASIC's 16-bit integer data type.
end

$lines

$constant false = 0
$constant true = FFFFH

rem - compute p mod q
function mod(p, q = integer) = integer
end = p - q * (p/q)

comment
  Compute, and optionally display, hailstone sequence for n.
  Return length of sequence or zero on overflow
end
function hailstone(n, display = integer) = integer
  var length = integer
  length = 1
  while (n <> 1) and (n > 0) do
    begin
      if display then print using "#####   ", n;
      if mod(n,2) = 0 then
        n = n / 2
      else
        n = (n * 3) + 1
     length = length + 1
    end
  if display then print using "#####   ", n
  rem - return 0 on overflow
  if n < 0 then length = 0
end = length

var n, limit, slen, longest, n_longest = integer

input "Display hailstone sequence for what number"; n
slen = hailstone(n, true)
print "Sequence length = "; slen

rem - find longest sequence before overflow
n = 2
longest = 1
slen = 1
limit = 1000;
print "Searching for longest sequence up to N =", limit," ..."
while (n < limit) and (slen <> 0) do
  begin
    slen = hailstone(n, false)
    if slen > longest then
      begin
        longest = slen
        n_longest = n
      end
    n = n + 1
  end
if slen = 0 then print "Search terminated with overflow at";n-1
print "Maximum sequence length =";longest;" for N =";n_longest

end


object HailstoneSequence extends App {
  def hailstone(n: Int): Stream[Int] =
    n #:: (if (n == 1) Stream.empty else hailstone(if (n % 2 == 0) n / 2 else n * 3 + 1))

  val nr = args.headOption.map(_.toInt).getOrElse(27)
  val collatz = hailstone(nr)
  println(s"Use the routine to show that the hailstone sequence for the number: $nr.")
  println(collatz.toList)
  println(s"It has ${collatz.length} elements.")
  println
  println(
    "Compute the number < 100,000, which has the longest hailstone sequence with that sequence's length.")
  val (n, len) = (1 until 100000).map(n => (n, hailstone(n).length)).maxBy(_._2)
  println(s"Longest hailstone sequence length= $len occurring with number $n.")
}


function x=hailstone(n)
    // iterative definition
    // usage: global verbose; verbose=%T; hailstone(27)
    global verbose
    x=0; loop=%T
    while(loop)
        x=x+1
        if verbose then
            printf('%i ',n)
        end
        if n==1 then
            loop=%F
        elseif modulo(n,2)==1 then
            n=3*n+1
        else
            n=n/2
        end
    end
endfunction

global verbose;
verbose=1;
N=hailstone(27);
printf('\n\n%i\n',N);

global verbose;
verbose=0;
N=100000;
M=zeros(N,1);
for k=1:N
  M(k)=hailstone(k);
end;
[maxLength,n]=max(M)