Executable library: Difference between revisions

m
m (→‎task 5: clarified what could be entered (of a list). -- ~~~~)
m (→‎{{header|Wren}}: Minor tidy)
 
(46 intermediate revisions by 25 users not shown)
Line 1:
{{task}}
{{omit from|GUISS}}
The general idea behind an executable library is to create a library that when used as a library does one thing; but has the ability to be run directly via command line. Thus the API comes with a CLI in the very same source code file.
{{omit from|Haskell}}
{{omit from|MATLAB}}
{{omit from|Maxima}}
{{omit from|Octave}}
{{omit from|R}}
{{omit from|SAS}}
{{omit from|Scilab}}
{{omit from|Stata}}
The general idea behind an executable library is to create a library
that when used as a library does one thing;
but has the ability to be run directly via command line.
Thus the API comes with a CLI in the very same source code file.
 
'''Task detail'''
Line 21 ⟶ 33:
=={{header|Ada}}==
 
In Ada, '''any parameterless procedure''' can either '''run as a (stand-alone) main program''', or can '''be called from another program''' like a library function. For the task at hand, this appears useful -- except for the following two obstacles:
For the task at hand, this appears useful -- except for the following two obstacles:
 
1. There are neither ingoing parameters into a parameterless procedure, nor is there a return value.
Line 29 ⟶ 42:
To overcome the first obstacle, we implement a very simplistic parameter passing mechanism in a package Parameter (''parameter.ads''): The global variable Parameter.X will hold the ingoing parameter, the other global variable Parameter.Y will take the return value. To overcome the second obstacle, we ensure that Parameter.X is 0 by default.
 
<langsyntaxhighlight Adalang="ada">package Parameter is
X: Natural := 0;
Y: Natural;
end Parameter;</langsyntaxhighlight>
 
Now comes our parameterless procedure Hailstone (''hailstone.adb''). Note that we are
Line 38 ⟶ 51:
[[Hailstone sequence#Alternative method]] to perform the real computation.
 
<langsyntaxhighlight Adalang="ada">with Ada.Text_IO, Parameter, Hailstones;
 
procedure Hailstone is
Line 86 ⟶ 99:
end;
end if;
end Hailstone;</langsyntaxhighlight>
 
If we compile this and run it, we get the following output.
 
If we compile this and run it, we get the following output:
<pre>> ./hailstone
Hailstone( 27 ) = ( 27, 82, 41, 124, ..., 8, 4, 2, 1 ); Length: 112
Line 97 ⟶ 109:
that essentially repeats the parameter profile. As our procedure is actually parameterless, this specification is more than trivial.
 
<syntaxhighlight lang Ada="ada">procedure Hailstone;</langsyntaxhighlight>
 
Finally, we write another parameterless procedure (''hailstone_test.adb''), that will call the procedure Hailstone. Note that we '''must''' change the Parameter.X to a value > 0 before calling Hailstone, otherwise, Hailstone would act as if it where the main program.
 
<langsyntaxhighlight Adalang="ada">with Hailstone, Parameter, Ada.Text_IO;
 
procedure Hailstone_Test is
Line 135 ⟶ 147:
Ada.Text_IO.Put_Line("The first such sequence: Hailstone("
& Integer'Image(Sample) & " ).");
end Hailstone_Test;</langsyntaxhighlight>.
 
Compiling and running this gives the following output:
 
<pre>> ./hailstone_test
Most frequent length: 72; 1467 sequences of that length.
Line 150 ⟶ 161:
{{works with|AutoHotkey_L}}
First we create the library, hailstone.ahk:
<langsyntaxhighlight AHKlang="ahk">#NoEnv
SetBatchLines, -1
 
Line 177 ⟶ 188:
until n=1
return out
}</syntaxhighlight>
}</lang>Running this directly gives the output:
Running this directly gives the output:
<pre>Length of hailstone 27: 112
Starts with 27, 82, 41, 124
Line 185 ⟶ 197:
 
Then we can create a file (test.ahk) that uses the library (note the #Include line):
<langsyntaxhighlight AHKlang="ahk">#NoEnv
#Include %A_ScriptDir%\hailstone.ahk
SetBatchLines -1
Line 201 ⟶ 213:
if (count > highestCount)
highestCount := count, highestN := length
MsgBox % "the most common length was " highestN "; it occurred " highestCount " times."</langsyntaxhighlight>
Running this '''does not''' trigger the output of the hailstone.ahk, instead it outputs this:
instead it outputs this:
<pre>the most common length was 72; it occurred 1467 times.</pre>
[[Link title]]
Line 208 ⟶ 221:
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
To meet the terms of this task the BBC BASIC run-time engine '''bbcwrun.exe''' must be installed on the target PC and the file extension '''.bbc''' must be associated with this executable. This is normally the case when ''BBC BASIC for Windows'' has been installed.
This is normally the case when ''BBC BASIC for Windows'' has been installed.
 
===Library===
This must be saved as the file HAILSTONE.BBC. It may be used as a library (see below) or executed directly.
It may be used as a library (see below) or executed directly.
<lang bbcbasic> seqlen% = FNhailstone(27)
<syntaxhighlight lang="bbcbasic"> seqlen% = FNhailstone(27)
PRINT "Sequence length for 27 is "; seqlen%
maxlen% = 0
Line 231 ⟶ 247:
L% += 1
ENDWHILE
= L% + 1</langsyntaxhighlight>
{{out}}
'''Output:'''
<pre>
Sequence length for 27 is 112
Line 238 ⟶ 254:
Its sequence length is 351
</pre>
 
===Client===
This uses the above program as a library:
<langsyntaxhighlight lang="bbcbasic"> INSTALL "HAILSTONE"
DIM freq%(351)
Line 257 ⟶ 274:
PRINT "The most common sequence length is " ; mostcommon%
PRINT "It occurs " ; max% " times"
END</langsyntaxhighlight>
{{out}}
'''Output:'''
<pre>
The most common sequence length is 72
Line 266 ⟶ 283:
=={{header|C}}==
Solution for Linux/GCC. First, header file hailstone.h:
<langsyntaxhighlight Clang="c">#ifndef HAILSTONE
#define HAILSTONE
Line 272 ⟶ 289:
void free_sequence(long *);
 
#endif/*HAILSTONE*/</langsyntaxhighlight>
Then the lib source code hailstone.c (actual name doesn't matter):
<langsyntaxhighlight Clang="c">#include <stdio.h>
#include <stdlib.h>
 
Line 317 ⟶ 334:
 
exit(0);
}</langsyntaxhighlight>
A program to use the lib (I call it test.c):
<langsyntaxhighlight Clang="c">#include <stdio.h>
#include "hailstone.h"
 
Line 338 ⟶ 355:
 
return 0;
}</langsyntaxhighlight>
 
Building the lib: <code>gcc -Wall -W -fPIC -shared -o libhail.so hailstone.c -lc -Wl,-e,hail_main</code>
Line 354 ⟶ 371:
 
For a serious library the <code>libhail.so</code> would have been put into a system lib dir, but for now we'll just leave it in the same directory, so to run the program, we need to give additional hints to tell it where to find the lib: <code>LD_LIBRARY_PATH=. ./hailtest</code>
 
=={{header|Clojure}}==
In a project's source directory, you might have a subfolder named <code>rosetta_code</code> with two Clojure source files:
<pre>
.
├── clojure.jar
└── rosetta_code
├── frequent_hailstone_lengths.clj
└── hailstone_sequence.clj
</pre>
The file <code>hailstone_sequence.clj</code> is an executable library:
<syntaxhighlight lang="clojure">(ns rosetta-code.hailstone-sequence)
 
(defn next-in-hailstone
"Returns the next number in the Hailstone sequence that starts with x.
If x is less than 2, returns nil."
[x]
(when (> x 1)
(if (even? x)
(/ x 2)
(inc (* 3 x)))))
 
(defn hailstone-seq
"Returns a lazy Hailstone sequence starting with the number x."
[x]
(take-while some?
(iterate next-in-hailstone x)))
 
(defn -main [& args]
(let [h27 (hailstone-seq 27)]
(printf "The Hailstone sequence starting at 27 contains %s elements:\n%s ... %s.\n"
(count h27)
(vec (take 4 h27))
(vec (take-last 4 h27)))
(let [[number length] (apply max-key second
(map (fn [x] [x (count (hailstone-seq x))])
(range 100000)))]
(printf "The number %s has the longest Hailstone sequence under 100000, of length %s.\n"
number length))))</syntaxhighlight>
You can run it from the command line (<code>clojure.jar</code> is [https://clojure.org/community/downloads the jar that contains the Clojure language]):
<pre>$ java -cp clojure.jar clojure.main -m rosetta-code.hailstone-sequence
The Hailstone sequence starting at 27 contains 112 elements:
[27 82 41 124] ... [8 4 2 1].
The number 77031 has the longest Hailstone sequence under 100000, of length 351.
</pre>
You can also use its functions from other programs. The file <code>frequent_hailstone_lengths.clj</code>:
<syntaxhighlight lang="clojure">(ns rosetta-code.frequent-hailstone-lengths
(:require [rosetta-code.hailstone-sequence
:refer [hailstone-seq]]))
 
(defn -main [& args]
(let [frequencies (apply merge-with +
(for [x (range 1 100000)]
{(count (hailstone-seq x)) 1}))
[most-frequent-length frequency]
(apply max-key val (seq frequencies))]
(printf (str "The most frequent Hailstone sequence length for numbers under 100000 is %s,"
" with a frequency of %s.\n")
most-frequent-length frequency)))</syntaxhighlight>
You can run it from the command line:
<pre>$ java -cp clojure.jar clojure.main -m rosetta-code.frequent-hailstone-lengths
The most frequent Hailstone sequence length for numbers under 100000 is 72, with a frequency of 1467.</pre>
Clojure also supports ahead-of-time compilation to class files, and the standard packaging tools [https://leiningen.org/ Leiningen] and [http://boot-clj.com/ Boot] provide meta-commands to compile and package Clojure programs into stand-alone runnable jars. At this point, Clojure has more or less the same executable library story as Java (class files can be named as the main entry point, and they can be included by other classes that import them).
 
=={{header|Déjà Vu}}==
 
The library, named <code>hailstone.deja</code>:
<langsyntaxhighlight lang="dejavu">local hailstone:
swap [ over ]
while < 1 dup:
Line 393 ⟶ 473:
!print( "number: " to-str max ", length: " to-str maxlen )
else:
@hailstone</langsyntaxhighlight>
 
The client:
<langsyntaxhighlight lang="dejavu">!import!hailstone
 
local :counts {}
Line 408 ⟶ 488:
set :maxlen counts! k
!print( "Maximum length: " to-str maxlen )
</syntaxhighlight>
</lang>
 
=={{header|Factor}}==
Line 415 ⟶ 495:
This vocabulary, ''rosetta.hailstone'', exports the word ''hailstone'', but also uses ''MAIN:'' to declare a main entry point.
 
<langsyntaxhighlight lang="factor">! rosetta/hailstone/hailstone.factor
USING: arrays io kernel math math.ranges prettyprint sequences vectors ;
IN: rosetta.hailstone
Line 445 ⟶ 525:
PRIVATE>
 
MAIN: main</langsyntaxhighlight>
 
There are two ways to run this program:
Line 462 ⟶ 542:
Any other Factor program can also use ''rosetta.hailstone'' as a regular vocabulary. This program only uses the word ''hailstone'' from that vocabulary, and never calls the main entry point of ''rosetta.hailstone''.
 
<langsyntaxhighlight lang="factor">! rosetta/hailstone/length/length.factor
USING: assocs kernel io math math.ranges prettyprint
rosetta.hailstone sequences ;
Line 488 ⟶ 568:
PRIVATE>
 
MAIN: main</langsyntaxhighlight>
 
<pre>$ ./factor -run=rosetta.hailstone.length
Line 495 ⟶ 575:
Among Hailstone sequences from 1 <= n < 100000,
there are 72 sequences of length 1467.</pre>
 
=={{header|Go}}==
To be directly executable, a Go application must contain a package called 'main' which includes a main() function from which execution begins automatically. Any other application is regarded as a library.
 
However, a package can consist of not just one but several source code files contained in the same directory.
 
Consequently, Go can emulate an executable library by splitting package 'main' into two files:
 
1. A file including the library code which includes (say) a libMain() function but no main() function as such.
 
2. A file including a main() function which calls libMain().
 
If these two files are 'run' as a package, then they can mimic executing the library code directly.
 
To use the library from another executable application, all that is needed is to copy the first file to the application's directory and then 'run' the files as a package. Care would be needed to ensure that there are no name clashes in the 'combined' package.
 
Note that, although the 'go run' command may look like it's launching an interpreter, it does in fact build an application from the package files in a temporary directory and then executes it in a single step.
 
To complete the task, first create these two files in the 'modulino' directory:
 
<syntaxhighlight lang="go">// modulino.go
package main
 
import "fmt"
 
// Function borrowed from Hailstone sequence task.
// 1st arg is the number to generate the sequence for.
// 2nd arg is a slice to recycle, to reduce garbage.
func hailstone(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 libMain() {
seq := hailstone(27, nil)
fmt.Println("\nHailstone sequence for the number 27:")
fmt.Println(" has", len(seq), "elements")
fmt.Println(" starts with", seq[0:4])
fmt.Println(" ends with", seq[len(seq)-4:])
 
var longest, length int
for i := 1; i < 100000; i++ {
if le := len(hailstone(i, nil)); le > length {
longest = i
length = le
}
}
fmt.Printf("\n%d has the longest Hailstone sequence, its length being %d.\n", longest, length)
}</syntaxhighlight>
 
<syntaxhighlight lang="go">// modulino_main.go
package main
 
func main() {
libMain()
}</syntaxhighlight>
 
To emulate an executable library:
{{output}}
<pre>
$ go run modulino
 
Hailstone sequence for the number 27:
has 112 elements
starts with [27 82 41 124]
ends with [8 4 2 1]
 
77031 has the longest Hailstone sequence, its length being 351.
</pre>
 
Now create this file in the 'hailstone' directory:
 
<syntaxhighlight lang="go">// hailstone.go
package main
 
import "fmt"
 
func main() {
freq := make(map[int]int)
for i := 1; i < 100000; i++ {
freq[len(hailstone(i, nil))]++
}
var mk, mv int
for k, v := range freq {
if v > mv {
mk = k
mv = v
}
}
fmt.Printf("\nThe Hailstone length returned most is %d, which occurs %d times.\n", mk, mv)
}</syntaxhighlight>
 
and copy modulino.go to the 'hailstone' directory. The library can then be used in the 'normal' way:
{{output}}
<pre>
$ go run hailstone
 
The Hailstone length returned most is 72, which occurs 1467 times.
</pre>
 
=={{header|Io}}==
 
'''HailStone.io'''
<syntaxhighlight lang="io">HailStone := Object clone
HailStone sequence := method(n,
if(n < 1, Exception raise("hailstone: expect n >= 1 not #{n}" interpolate))
n = n floor // make sure integer value
stones := list(n)
while (n != 1,
n = if(n isEven, n/2, 3*n + 1)
stones append(n)
)
stones
)
 
if( isLaunchScript,
out := HailStone sequence(27)
writeln("hailstone(27) has length ",out size,": ",
out slice(0,4) join(" ")," ... ",out slice(-4) join(" "))
maxSize := 0
maxN := 0
for(n, 1, 100000-1,
out = HailStone sequence(n)
if(out size > maxSize,
maxSize = out size
maxN = n
)
)
writeln("For numbers < 100,000, ", maxN,
" has the longest sequence of ", maxSize, " elements.")
)</syntaxhighlight>
'''client.io'''
<syntaxhighlight lang="io">counts := Map clone
for(n, 1, 100000-1,
out := HailStone sequence(n)
key := out size asCharacter
counts atPut(key, counts atIfAbsentPut(key, 0) + 1)
)
 
maxCount := counts values max
lengths := list()
counts foreach(k,v,
if(v == maxCount, lengths append(k at(0)))
)
 
if(lengths size == 1,
writeln("The most frequent sequence length for n < 100,000 is ",lengths at(0),
" occurring ",maxCount," times.")
,
writeln("The most frequent sequence lengths for n < 100,000 are:\n",
lengths join(",")," occurring ",maxCount," times each.")
)</syntaxhighlight>
'''Terminal Session'''
<pre>$ io HailStone.io
hailstone(27) has length 112: 27 82 41 124 ... 8 4 2 1
For numbers < 100,000, 77031 has the longest sequence of 351 elements.
$ io client.io
The most frequent sequence length for n < 100,000 is 72 occurring 1467 times.
$</pre>
Io has a built-in auto importer that will attempt to automatically
import a file with the same name (plus "io" extension) as an undefined
prototype object when it is first referenced. To be imported the first letter of the
prototype name must also be upper case which by convention indicates a
prototype that has the same role as a class in class based object-oriented
languages. The Importer's default search path is the current working
directory, but you can add search paths using <code>Importer addSearchPath()</code>.
 
=={{header|J}}==
Line 500 ⟶ 756:
This is the executable library:
 
<syntaxhighlight lang="j">#!/usr/bin/ijconsole
<lang j>hailseq=: -:`(1 3&p.)@.(2&|) ^:(1 ~: ]) ^:a:"0
hailseq=: -:`(1 3&p.)@.(2&|) ^:(1 ~: ]) ^:a:"0
9!:29]1
9!:27'main 0'
Line 510 ⟶ 767:
smoutput 'less than 100000 (and finding that sequence length):'
smoutput (I.@(= >./),>./) #@hailseq i.1e5
)</langsyntaxhighlight>
 
Running it might look like this:
 
<langsyntaxhighlight lang="j"> load jpath '~temp/hailseq.ijs'
Hailstone sequence for the number 27
27 82 41 124 62 31 94 47 142 71 214 107 322 161 484 242 121 364 182 91 274 137 412 206 103 310 155 466 233 700 350 175 526 263 790 395 1186 593 1780 890 445 1336 668 334 167 502 251 754 377 1132 566 283 850 425 1276 638 319 958 479 1438 719 2158 1079 3238 ...
Finding number with longest hailstone sequence which is
less than 100000 (and finding that sequence length):
77031 351</langsyntaxhighlight>
 
This is the program which uses the library part of that executable library:
 
<langsyntaxhighlight lang="j">require '~temp/hailseq.ijs'
9!:29]1
9!:27'main 0'
Line 531 ⟶ 788:
smoutput {:{.\:~ (#/.~,.~.) #@hailseq }.i.1e5
)
</syntaxhighlight>
</lang>
 
Running it might look like this:
<syntaxhighlight lang="j"> load jpath '~temp/66.ijs'
 
<lang j> load jpath '~temp/66.ijs'
Finding most frequent hailstone sequence length for
Hailstone sequences for whole numbers less than 100000
72</langsyntaxhighlight>
 
Notes: <code>9!:29]1</code> tells the interpeter to run a phrase. <code>9!:27'phrase'</code> tells the interpeter the phrase to execute. (<code>9!:</code> means, in essence: standard library number 9, and <code>9!:29</code> identifies a specific entry point in that library.) In 66.ijs we can not use the presence of <code>9!:29]1</code> from <code>hailseq.ijs</code> because hailseq.ijs was loaded with require which means that if it had already been loaded it will not be loaded again. (And, <code>66</code> here is just an arbitrary temporary file name.)
In 66.ijs we can not use the presence of <code>9!:29]1</code> from <code>hailseq.ijs</code> because hailseq.ijs was loaded with require which means that if it had already been loaded it will not be loaded again.
(And, <code>66</code> here is just an arbitrary temporary file name.)
 
=={{header|Java}}==
 
Java files are compiled into bytecode class files. The CLASSPATH will specify the location of class files.
 
===Library===
<syntaxhighlight lang="java">
import java.util.ArrayList;
import java.util.List;
 
// task 1
public class HailstoneSequence {
 
public static void main(String[] args) {
// task 2
int n = 27;
List<Long> sequence27 = hailstoneSequence(n);
System.out.printf("Hailstone sequence for %d has a length of %d:%nhailstone(%d) = %s%n", n, sequence27.size(), n, sequence27);
// task 3
int maxN = 0;
int maxLength = 0;
for ( int i = 1 ; i < 100_000 ; i++ ) {
int seqLength = hailstoneSequence(i).size();
if ( seqLength > maxLength ) {
maxLength = seqLength;
maxN = i;
}
}
System.out.printf("Longest hailstone sequence less than 100,000: hailstone(%d).length() = %d", maxN, maxLength);
}
public static List<Long> hailstoneSequence(long n) {
if ( n <= 0 ) {
throw new IllegalArgumentException("Must be grater than or equal to zero.");
}
List<Long> sequence = new ArrayList<>();
sequence.add(n);
while ( n > 1 ) {
if ( (n & 1) == 0 ) {
n /= 2;
}
else {
n = 3 * n + 1;
}
sequence.add(n);
}
return sequence;
}
}
</syntaxhighlight>
{{out}}
<pre>
Hailstone sequence for 27 has a length of 112:
hailstone(27) = [27, 82, 41, 124, 62, 31, 94, 47, 142, 71, 214, 107, 322, 161, 484, 242, 121, 364, 182, 91, 274, 137, 412, 206, 103, 310, 155, 466, 233, 700, 350, 175, 526, 263, 790, 395, 1186, 593, 1780, 890, 445, 1336, 668, 334, 167, 502, 251, 754, 377, 1132, 566, 283, 850, 425, 1276, 638, 319, 958, 479, 1438, 719, 2158, 1079, 3238, 1619, 4858, 2429, 7288, 3644, 1822, 911, 2734, 1367, 4102, 2051, 6154, 3077, 9232, 4616, 2308, 1154, 577, 1732, 866, 433, 1300, 650, 325, 976, 488, 244, 122, 61, 184, 92, 46, 23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1]
Longest hailstone sequence less than 100,000: hailstone(77031).length() = 351
</pre>
 
===Client===
<syntaxhighlight lang="java">
import java.util.HashMap;
import java.util.Map;
import java.util.stream.IntStream;
 
public class ExecutableLibrary {
 
public static void main(String[] args) {
Map<Integer,Integer> lengthMap = new HashMap<>();
IntStream.range(1, 100_000)
.map(n -> HailstoneSequence.hailstoneSequence(n).size())
.forEach(len -> lengthMap.merge(len, 1, (v1, v2) -> v1 + v2));
int mostOften = lengthMap.values()
.stream()
.mapToInt(x -> x)
.max().orElse(-1);
 
System.out.printf("The most frequent hailstone length for n < 100,000 is %d.%n", mostOften);
}
 
}
</syntaxhighlight>
{{out}}
<pre>
The most frequent hailstone length for n < 100,000 is 1467.
</pre>
 
=={{header|Julia}}==
A Julia module can check to see if it is also the file run from the command lime by checking the PROGRAM_NAME variable.
<syntaxhighlight lang="julia">
############### in file hailstone.jl ###############
module Hailstone
 
function hailstone(n)
ret = [n]
while n > 1
if n & 1 > 0
n = 3n + 1
else
n = Int(n//2)
end
append!(ret, n)
end
return ret
end
 
export hailstone
 
end
 
if PROGRAM_FILE == "hailstone.jl"
using Hailstone
h = hailstone(27)
n = length(h)
println("The sequence of hailstone(27) is:\n $h.\nThis sequence is of length $n. It starts with $(h[1:4]) and ends with $(h[n-3:end]).")
end
############ in file moduletest.jl ####################
include("hailstone.jl")
using Hailstone
function countstones(mi, mx)
lengths2occurences = Dict()
mostfreq = mi
maxcount = 1
for i in mi:mx
h = hailstone(i)
n = length(h)
if haskey(lengths2occurences, n)
newoccurences = lengths2occurences[n] + 1
if newoccurences > maxcount
maxcount = newoccurences
mostfreq = n
end
lengths2occurences[n] = newoccurences
else
lengths2occurences[n] = 1
end
end
mostfreq, maxcount
end
 
nlen, cnt = countstones(1,99999)
 
print("The most common hailstone sequence length for hailstone(n) for 1 <= n < 100000 is $nlen, which occurs $cnt times.")
</syntaxhighlight>
{{output}}<pre>
Running hailstone.jl standalone:
The sequence of hailstone(27) is:
[27, 82, 41, 124, 62, 31, 94, 47, 142, 71, 214, 107, 322, 161, 484, 242, 121, 364, 182, 91, 274, 137, 412, 206, 103, 310, 155, 466, 233, 700, 350, 175, 526, 263, 790, 395, 1186, 593, 1780, 890, 445, 1336, 668, 334, 167, 502, 251, 754, 377, 1132, 566, 283, 850, 425, 1276, 638, 319, 958, 479, 1438, 719, 2158, 1079, 3238, 1619, 4858, 2429, 7288, 3644, 1822, 911, 2734, 1367, 4102, 2051, 6154, 3077, 9232, 4616, 2308, 1154, 577, 1732, 866, 433, 1300, 650, 325, 976, 488, 244, 122, 61, 184, 92, 46, 23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1].
This sequence is of length 112. It starts with [27, 82, 41, 124] and ends with [8, 4, 2, 1].
Running the program that uses the Hailstone module:
The most common hailstone sequence length for hailstone(n) for 1 <= n < 100000 is 72, which occurs 1467 times.
</pre>
 
=={{header|Limbo}}==
{{incomplete|Limbo|Unsure from the output whether execution of execlib.b on its own produces first part of output independant of any later calls to execsexeclib.b}}
There's no real difference in compilation or output for libraries versus commands in Inferno; commands (by convention) are expected to define an <code>init()</code> function that accepts a reference to a graphical context and a list of strings (i.e., the argument list) in order to satisy the type-checker. So this task is fairly simple. First, <code>execlib.b</code> looks like this:
 
There's no real difference in compilation or output
<lang Limbo>implement Execlib;
for libraries versus commands in Inferno;
commands (by convention) are expected to define an <code>init()</code> function that accepts a reference to a graphical context and a list of strings (i.e., the argument list) in order to satisy the type-checker.
So this task is fairly simple.
First, <code>execlib.b</code> looks like this:
 
<syntaxhighlight lang="limbo">implement Execlib;
 
include "sys.m"; sys: Sys;
Line 599 ⟶ 1,013:
return i :: hailstone(big 3 * i + big 1);
}
</syntaxhighlight>
</lang>
 
And <code>execsexeclib.b</code> (which executes <code>execlib</code>) looks like this:
 
<langsyntaxhighlight Limbolang="limbo">implement ExecsExeclib;
 
include "sys.m"; sys: Sys;
Line 648 ⟶ 1,062:
raise "fail:errors";
}
</syntaxhighlight>
</lang>
 
{{out}}
Line 654 ⟶ 1,068:
<pre>
% apply {limbo $1} *execlib.b
% ./execlib
% apply {echo Running $1; $1} *execlib.dis
Running execlib.dis
hailstone(27): 27, 82, 41, 124, ⋯, 8, 4, 2, 1 (length 112)
hailstone(77031) has length 351
% ./execsexeclib
Running execsexeclib.dis
The most common sequence length is 72 (encountered 1467 times)
</pre>
 
=={{header|Lua}}==
The library is called hailstone.lua:
<syntaxhighlight lang="lua">#!/usr/bin/env luajit
bit32=bit32 or bit
local lib={
hailstone=function(n)
local seq={n}
while n>1 do
n=bit32.band(n,1)==1 and 3*n+1 or n/2
seq[#seq+1]=n
end
return seq
end
}
 
if arg[0] and arg[0]:match("hailstone.lua") then
local function printf(fmt, ...) io.write(string.format(fmt, ...)) end
local seq=lib.hailstone(27)
printf("27 has %d numbers in sequence:\n",#seq)
for _,i in ipairs(seq) do
printf("%d ", i)
end
printf("\n")
else
return lib
end
</syntaxhighlight>
 
The executable is called hailtest.lua:
 
<syntaxhighlight lang="lua">#!/usr/bin/env luajit
local lib=require"hailstone"
local longest,longest_i=0,0
for i=1,1e5 do
local len=#lib.hailstone(i)
if len>longest then
longest_i=i
longest=len
end
end
print("Longest sequence at "..longest_i..", length "..longest)
</syntaxhighlight>
 
{{out}}
<pre>> ./hailstone.lua
27 has 112 numbers in sequence:
27 82 41 124 62 31 94 47 142 71 214 107 322 161 484 242 121 364 … 8 4 2 1
> ./hailtest.lua
Longest sequence at 77031, length 351
</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
===Library===
<syntaxhighlight lang="mathematica">hailstone[1] = {1};
hailstone[n_] :=
hailstone[n] = Prepend[hailstone[If[EvenQ[n], n/2, 3 n + 1]], n];
If[$ScriptCommandLine[[1]] == $Input,
val = hailstone[27];
Print["hailstone(27) starts with ", val[[;; 4]], ", ends with ",
val[[-4 ;;]], ", and has length ", Length[val], "."];
val = MaximalBy[Range[99999], Length@*hailstone][[1]];
Print[val, " has the longest hailstone sequence with length ",
Length[hailstone[val]], "."]];</syntaxhighlight>
{{out}}
<pre>hailstone(27) starts with {27, 82, 41, 124}, ends with {8, 4, 2, 1}, and has length 112.
77031 has the longest hailstone sequence with length 351.</pre>
===Client===
This assumes that the library is named <tt>hailstone.m</tt>.
<syntaxhighlight lang="mathematica"><< hailstone.m;
Print["The most common hailstone length is ",
Commonest[Length@*hailstone /@ Range[99999]][[1]], "."];</syntaxhighlight>
{{out}}
<pre>The most common hailstone length is 72.</pre>
 
=={{header|Nanoquery}}==
The global boolean value 'main' is true is the program is being executed directly and false if it is being imported as a library.
<syntaxhighlight lang="nanoquery">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
 
if main
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
end</syntaxhighlight>
 
=={{header|NetRexx}}==
Line 684 ⟶ 1,208:
Using this JAR file as a library, the following program can use the <tt>hailstone(N)</tt> method to complete the task:
 
<langsyntaxhighlight NetRexxlang="netrexx">/* NetRexx */
options replace format comments java crossref symbols nobinary
 
Line 719 ⟶ 1,243:
say 'The length of hailstone sequence that is most common in the range' beginNum '<= N <' endNum 'is' mostOftenNum'. It occurs' mostOftenCount 'times.'
return
</syntaxhighlight>
</lang>
 
The program can then be launched with the <tt>java</tt> command. In this sample the JAR file is included via the <tt>-cp</tt> switch:
Line 725 ⟶ 1,249:
<pre>$ java -cp .:RHailstoneSequence.jar RHailstoneSequenceUser
The length of hailstone sequence that is most common in the range 1 <= N < 100000 is 72. It occurs 1467 times.</pre>
 
=={{header|Nim}}==
<syntaxhighlight lang="nim">proc hailstone*(n: int): auto =
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:
let h = hailstone 27
assert h.len == 112 and h[0..3] == @[27,82,41,124] and h[h.high-3..h.high] == @[8,4,2,1]
var m, mi = 0
for i in 1 ..< 100_000:
let n = hailstone(i).len
if n > m:
m = n
mi = i
echo "Maximum length ", m, " was found for hailstone(", mi, ") for numbers <100,000"</syntaxhighlight>
 
In Nim the value <code>isMainModule</code> is set at compiletime, and we can use it with <code>when</code> (a compiletime if).
 
'''Library Importing Example'''
<syntaxhighlight lang="nim">import hailstone, tables
 
var t = initCountTable[int]()
 
for i in 1 ..< 100_000:
t.inc(hailstone(i).len)
 
let (val, cnt) = t.largest()
echo "The length of hailstone sequence that is most common for"
echo "hailstone(n) where 1<=n<100000, is ", val, ". It occurs ", cnt, " times."</syntaxhighlight>
 
{{out}}
<pre>The length of hailstone sequence that is most common for
hailstone(n) where 1<=n<100000, is 72. It occurs 1467 times.</pre>
 
=={{header|PARI/GP}}==
Linux solution (i386 and x86_64).
 
Library file hailstone.c:
<syntaxhighlight lang="c">#include <pari/pari.h>
 
#define HAILSTONE1 "n=1;print1(%d,\": \");apply(x->while(x!=1,if(x/2==x\\2,x/=2,x=x*3+1);n++;print1(x,\", \")),%d);print(\"(\",n,\")\n\")"
#define HAILSTONE2 "m=n=0;for(i=2,%d,h=1;apply(x->while(x!=1,if(x/2==x\\2,x/=2,x=x*3+1);h++),i);if(m<h,m=h;n=i));print(n,\": \",m)"
 
void hailstone1(int x)
{
char buf[1024];
 
snprintf(buf, sizeof(buf), HAILSTONE1, x, x);
 
pari_init(1000000, 2);
 
geval(strtoGENstr(buf));
 
pari_close();
}
 
void hailstone2(int range)
{
char buf[1024];
 
snprintf(buf, sizeof(buf), HAILSTONE2, range);
 
pari_init(1000000, 2);
 
geval(strtoGENstr(buf));
 
pari_close();
}
 
#if __i386__
const char _hail[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2";
#else // __x86_64__
const char _hail[] __attribute__((section(".interp"))) = "/lib64/ld-linux-x86-64.so.2";
#endif
 
int main(void)
{
hailstone1(27);
hailstone2(100000);
 
exit(0);
}</syntaxhighlight>
Compile hailstone.c: ''gcc -O2 -Wall hailstone.c -fPIC -shared -o libhailstone.so -lpari -Wl,-e,main''
 
Execute library: ''./libhailstone.so'':
<pre>27: 82, 41, 124, 62, 31, 94, 47, 142, 71, 214, 107, 322, 161, 484, 242, 121, 364, 182, 91, 274, 137, 412, 206, 103, 310, 155, 466, 233, 700, 350, 175, 526, 263, 790, 395, 1186, 593, 1780, 890, 445, 1336, 668, 334, 167, 502, 251, 754, 377, 1132, 566, 283, 850, 425, 1276, 638, 319, 958, 479, 1438, 719, 2158, 1079, 3238, 1619, 4858, 2429, 7288, 3644, 1822, 911, 2734, 1367, 4102, 2051, 6154, 3077, 9232, 4616, 2308, 1154, 577, 1732, 866, 433, 1300, 650, 325, 976, 488, 244, 122, 61, 184, 92, 46, 23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1, (112)
 
77031: 351</pre>
----
Main program linking libhailstone.so... main.c:
<syntaxhighlight lang="c">void hailstone1(int);
 
int main(void)
{
hailstone1(27);
 
return 0;
}</syntaxhighlight>
Compile main.c: ''gcc -O2 -Wall main.c -o main -L. libhailstone.so''
 
Execute main program: ''LD_LIBRARY_PATH=. ./main'' :
<pre>27: 82, 41, 124, 62, 31, 94, 47, 142, 71, 214, 107, 322, 161, 484, 242, 121, 364, 182, 91, 274, 137, 412, 206, 103, 310, 155, 466, 233, 700, 350, 175, 526, 263, 790, 395, 1186, 593, 1780, 890, 445, 1336, 668, 334, 167, 502, 251, 754, 377, 1132, 566, 283, 850, 425, 1276, 638, 319, 958, 479, 1438, 719, 2158, 1079, 3238, 1619, 4858, 2429, 7288, 3644, 1822, 911, 2734, 1367, 4102, 2051, 6154, 3077, 9232, 4616, 2308, 1154, 577, 1732, 866, 433, 1300, 650, 325, 976, 488, 244, 122, 61, 184, 92, 46, 23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1, (112)</pre>
 
=={{header|Pascal}}==
{{works with|FPC}}
Library:
<syntaxhighlight lang="pascal">
uses
DynLibs;
type
THailSeq = record
Data: PCardinal;
Count: Longint;
end;
var
Buffer: array[0..511] of Cardinal;
 
function Hailstone(aValue: Cardinal): THailSeq;
var
I: Longint;
begin
Hailstone.Count := 0;
Hailstone.Data := nil;
if (aValue <> 0) and (aValue <= 200000) then begin
Buffer[0] := aValue;
I := 1;
repeat
if Odd(aValue) then
aValue := Succ((3 * aValue))
else
aValue := aValue div 2;
Buffer[I] := aValue;
Inc(I);
until aValue = 1;
Hailstone.Count := I;
Hailstone.Data := @Buffer;
end;
end;
 
procedure PrintArray(const Prefix: string; const a: array of Cardinal);
var
I: Longint;
begin
Write(Prefix, '[');
for I := 0 to High(a) - 1 do Write(a[I], ', ');
WriteLn(a[High(a)], ']');
end;
 
exports
Hailstone;
var
hs: THailSeq;
I, Value: Cardinal;
MaxLen: Longint;
begin
hs := Hailstone(27);
WriteLn('Length of Hailstone(27) is ', hs.Count, ',');
PrintArray('it starts with ', hs.Data[0..3]);
PrintArray('and ends with ', hs.Data[hs.Count-4..hs.Count-1]);
Value := 0;
MaxLen := 0;
for I := 1 to 100000 do begin
hs := Hailstone(I);
if hs.Count > MaxLen then begin
MaxLen := hs.Count;
Value := I;
end;
end;
WriteLn('Maximum length ', MaxLen, ' was found for Hailstone(', Value, ')');
end.
</syntaxhighlight>
build
<syntaxhighlight lang="shell">
Linux64: fpc <source file name> -Cg -k-pie -oexec_lib
Win64: fpc <source file name> -Cg -oexec_lib.exe
</syntaxhighlight>
when run as executable:
{{out}}
<pre>
Length of Hailstone(27) is 112,
it starts with [27, 82, 41, 124]
and ends with [8, 4, 2, 1]
Maximum length 351 was found for Hailstone(77031)
</pre>
Client:
<syntaxhighlight lang="pascal">
{$h+}
uses
SysUtils, DynLibs;
const
LIB_NAME = {$ifdef windows}'exec_lib.exe'{$else}'exec_lib'{$endif};
type
THailSeq = record
Data: PCardinal;
Count: Longint;
end;
THailstone = function(aValue: Cardinal): THailSeq;
TCounts = array[0..511] of Longint;
var
LibName: string;
hLib: TLibHandle;
Fun: THailstone;
I, Len, Count, c: Longint;
Counts: TCounts;
begin
LibName := ExtractFilePath(ParamStr(0))+LIB_NAME;
hLib := LoadLibrary(LibName);
if hLib = NilHandle then begin
WriteLn('Can not load library ', LibName); Halt(1);
end;
Pointer(Fun) := GetProcAddress(hLib, 'Hailstone');
if Pointer(Fun) = nil then begin
WriteLn('Can not find Hailstone() function'); Halt(2);
end;
Counts := Default(TCounts);
Count := 0;
Len := 0;
for I := 1 to 100000 do begin
c := Fun(I).Count;
Inc(Counts[c]);
if Counts[c] > Count then begin
Count := Counts[c];
Len := c;
end;
end;
UnloadLibrary(hLib);
WriteLn('The most common Hailstone sequence length in the specified range is ',
Len, ', it occurs ', Count, ' times.');
end.
</syntaxhighlight>
Both executables must be placed in the same folder.
{{out}}
<pre>
The most common Hailstone sequence length in the specified range is 72, it occurs 1467 times.
</pre>
 
=={{header|Perl}}==
Lib package in file <code>Hailstone.pm</code>:<lang perl>package Hailstone;
<syntaxhighlight lang="perl">package Hailstone;
 
sub seq {
Line 752 ⟶ 1,519:
}
 
1;</langsyntaxhighlight>
Main program in file <code>test.pl</code>:<langsyntaxhighlight lang="perl">use Hailstone;
use strict;
use warnings;
Line 763 ⟶ 1,530:
my ($most_frequent) = sort {$seqs{$b} <=> $seqs{$a}} keys %seqs;
print "Most frequent length: $most_frequent ($seqs{$most_frequent} occurrences)\n";</langsyntaxhighlight>
Running the lib: <pre>% perl Hailstone.pm
seq of 27 - 112 elements: 27 82 41 124 62 31 94 47 142 ... 10 5 16 8 4 2 1
Line 770 ⟶ 1,537:
Most frequent length: 72 (1467 occurrences)</pre>
 
=={{header|Perl 6Phix}}==
Simply test whether include_file() returns 1. hail.exw:
The library can be written as a module:
<syntaxhighlight lang="phix">--global (if you want to be able to call this from test.exw)
<lang perl6>module Hailstone {
our subfunction hailstone($atom n) is export {
sequence s = {n}
$n, { $_ %% 2 ?? $_ div 2 !! $_ * 3 + 1 } ... 1
}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
 
global function hailstone_count(atom n)
sub MAIN {
integer count = 1
say "hailstone(27) = {.[^4]} [...] {.[*-4 .. *-1]}" given Hailstone::hailstone 27;
while n!=1 do
}</lang>
if remainder(n,2)=0 then
n /= 2
else
n = 3*n+1
end if
count += 1
end while
return count
end function
 
if include_file()==1 then
It can be run with:
<lang shell>$ perl6 Hailstone.pm</lang>
sequence s = hailstone(27)
integer ls = length(s)
s[5..-5] = {".."}
puts(1,"hailstone(27) = ")
? s
printf(1,"length = %d\n\n",ls)
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})
end if</syntaxhighlight>
{{out}}
<pre>
<pre>hailstone(27) = 27 82 41 124 [...] 8 4 2 1</pre>
hailstone(27) = {27,82,41,124,"..",8,4,2,1}
length = 112
 
The longest hailstone sequence under 100,000 is 77031 with 351 elements.
It can then be used with a program such as:
</pre>
<lang perl6>use Hailstone;
test.exw:
my %score; %score{hailstone($_).elems}++ for 1 .. 100_000;
<syntaxhighlight lang="phix">include hail.exw
say "Most common lengh is {.key}, occuring {.value} times." given max :by(*.value), %score;</lang>
 
sequence counts = {}
Called with a command line as:
for i=1 to 100000 do
<pre>$ PERL6LIB=. perl6 test-hailstone.p6</pre>
integer l = hailstone_count(i)
if length(counts)<l then
counts &= repeat(0,l-length(counts))
end if
counts[l] += 1
end for
printf(1,"The hailstone length returned most often between 1 and 100,000 is %d.\n",{largest(counts,1)})</syntaxhighlight>
{{out}}
<pre>
The hailstone length returned most often between 1 and 100,000 is 72.
</pre>
 
=={{header|PicoLisp}}==
The environment variable PERL6LIB might be necessary if the file Hailstone.pm is not in the standard library path for Perl 6.
There is no formal difference between libraries and other executable files
in PicoLisp.
Any function in a library can be called from the command line
by prefixing it with '-'.
Create an executable file (chmod +x) "hailstone.l":
<syntaxhighlight lang="picolisp">#!/usr/bin/picolisp /usr/lib/picolisp/lib.l
 
(de hailstone (N)
(make
(until (= 1 (link N))
(setq N
(if (bit? 1 N)
(inc (* N 3))
(/ N 2) ) ) ) ) )
 
(de hailtest ()
(let L (hailstone 27)
(test 112 (length L))
(test (27 82 41 124) (head 4 L))
(test (8 4 2 1) (tail 4 L)) )
(let N (maxi '((N) (length (hailstone N))) (range 1 100000))
(test 77031 N)
(test 351 (length (hailstone N))) )
(println 'OK)
(bye) )</syntaxhighlight>
and an executable file (chmod +x) "test.l":
<syntaxhighlight lang="picolisp">#!/usr/bin/picolisp /usr/lib/picolisp/lib.l
 
(load "hailstone.l")
 
(let Len NIL
(for N 100000
(accu 'Len (length (hailstone N)) 1) )
(let M (maxi cdr Len)
(prinl "The hailstone length returned most often is " (car M))
(prinl "It is returned " (cdr M) " times") ) )
(bye)</syntaxhighlight>
Test:
<pre>$ ./hailstone.l -hailtest
OK
 
$ ./test.l
The hailstone length returned most often is 72
It is returned 1467 times</pre>
 
=={{header|Pike}}==
Line 807 ⟶ 1,666:
 
both can be used as an executable.
<langsyntaxhighlight Pikelang="pike">#!/usr/bin/env pike
int next(int n)
Line 845 ⟶ 1,704:
}
write("longest sequence starting at %d has %d elements\n", longest->start, longest->length);
}</langsyntaxhighlight>
 
if run directly we get:
Line 855 ⟶ 1,714:
note that the . in .HailStone only signifies calling a class or module from the current directory.
the analyze function is identical in both examples:
<langsyntaxhighlight Pikelang="pike">void main()
{
.HailStone HailStone = .HailStone();
Line 879 ⟶ 1,738:
}
write("most common length %d appears %d times\n", max->length, max->count);
}</langsyntaxhighlight>
 
a module is already instantiated so we can use it directly.
like above the initial . in .Hailstone.hailstone only signifies the current directory, the second . is a member reference resolved at compile time.
<langsyntaxhighlight Pikelang="pike">void main()
{
mapping long = ([]);
Line 905 ⟶ 1,764:
}
write("most common length %d appears %d times\n", max->length, max->count);
}</langsyntaxhighlight>
 
Output{{out}} for both examples:
<pre>
most common length 72 appears 1467 times
</pre>
 
=={{header|PicoLisp}}==
There is no formal difference between libraries and other executable files in PicoLisp. Any function in a library can be called from the command line by prefixing it with '-'. Create an executable file (chmod +x) "hailstone.l":
<lang PicoLisp>#!/usr/bin/picolisp /usr/lib/picolisp/lib.l
 
(de hailstone (N)
(make
(until (= 1 (link N))
(setq N
(if (bit? 1 N)
(inc (* N 3))
(/ N 2) ) ) ) ) )
 
(de hailtest ()
(let L (hailstone 27)
(test 112 (length L))
(test (27 82 41 124) (head 4 L))
(test (8 4 2 1) (tail 4 L)) )
(let N (maxi '((N) (length (hailstone N))) (range 1 100000))
(test 77031 N)
(test 351 (length (hailstone N))) )
(println 'OK)
(bye) )</lang>
and an executable file (chmod +x) "test.l":
<lang PicoLisp>#!/usr/bin/picolisp /usr/lib/picolisp/lib.l
 
(load "hailstone.l")
 
(let Len NIL
(for N 100000
(accu 'Len (length (hailstone N)) 1) )
(let M (maxi cdr Len)
(prinl "The hailstone length returned most often is " (car M))
(prinl "It is returned " (cdr M) " times") ) )
(bye)</lang>
Test:
<pre>$ ./hailstone.l -hailtest
OK
 
$ ./test.l
The hailstone length returned most often is 72
It is returned 1467 times</pre>
 
=={{header|Python}}==
Line 956 ⟶ 1,775:
 
The entry is copied below and, for this task needs to be in a file called <code>hailstone.py</code>:
<langsyntaxhighlight lang="python">def hailstone(n):
seq = [n]
while n>1:
Line 967 ⟶ 1,786:
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)))</langsyntaxhighlight>
 
In the case of the Python language the interpreter maintains a module level variable called __name__. If the file hailstone.py is ''imported'' (as <code>import hailstone</code>), then the __name__ variable is set to the import name of 'hailstone' and the <code>if __name__ == '__main__'</code> expression would then be false, and only the hailstone function is available to the importer.
Line 976 ⟶ 1,795:
 
The second executable is the file <code>common_hailstone_length.py</code> with this content:
<langsyntaxhighlight lang="python">from collections import Counter
 
def function_length_frequency(func, hrange):
Line 988 ⟶ 1,807:
print("The length of hailstone sequence that is most common for\n"
"hailstone(n) where 1<=n<%i, is %i. It occurs %i times."
% (upto, hlen, freq))</langsyntaxhighlight>
 
Both files could be in the same directory. (That is the easiest way to make the library known to its importer for this example)
 
{{out}}
'''Sample output'''
 
On executing the file common_hailstone_length.py it loads the library and produces the following result:
<pre>The length of hailstone sequence that is most common for
Line 1,010 ⟶ 1,828:
is one. When a file is used as a library (with <tt>require</tt>), the toplevel
expressions are executed as well, but the <tt>main</tt> is <em>not</em>
executed.
executed. The idea is that toplevel expressions might be used to initialize
The idea is that toplevel expressions might be used to initialize state
state that the library needs -- a good example here is the initialization of
that the memoizationlibrary hashneeds table.-- a (Notegood thatexample thishere is better than the common hacksinitialization of
of the memoization hash table.
check-the-loaded-script-name, since it is robust against failures due to
(Note that this is better than the common hacks of check-the-loaded-script-name, since it is robust against failures due to symlinks, case normalization, etc etc.)
 
We start with a "<tt>hs.rkt</tt>" file that has the exact code from the
Line 1,020 ⟶ 1,838:
function is now provided, and the demonstration printout is pushed into a
<tt>main</tt> submodule:
<syntaxhighlight lang="racket">
<lang Racket>
#lang racket
 
Line 1,042 ⟶ 1,860:
(printf "for x<=~s, ~s has the longest sequence with ~s items\n"
N (car longest) (cdr longest)))
</syntaxhighlight>
</lang>
 
Running it directly produces the same output as [[Hailstone sequence#Racket]]:
<pre>
Line 1,053 ⟶ 1,872:
And now this can be used from a second source file, "<tt>hsfreq.rkt</tt>" as a
library:
<syntaxhighlight lang="racket">
<lang Racket>
#lang racket
(require "hs.rkt")
Line 1,066 ⟶ 1,885:
(printf "Most frequent sequence length for x<=~s: ~s, appearing ~s times\n" N
(cdr best) (car best))
</syntaxhighlight>
</lang>
 
<pre>
Line 1,072 ⟶ 1,891:
Most frequent sequence length for x<=100000: 72, appearing 1467 times
</pre>
 
=={{header|Raku}}==
(formerly Perl 6)
The library can be written as a module:
<syntaxhighlight lang="raku" line>module Hailstone {
our sub hailstone($n) is export {
$n, { $_ %% 2 ?? $_ div 2 !! $_ * 3 + 1 } ... 1
}
}
 
sub MAIN {
say "hailstone(27) = {.[^4]} [...] {.[*-4 .. *-1]}" given Hailstone::hailstone 27;
}</syntaxhighlight>
 
It can be run with:
<syntaxhighlight lang="shell">$ raku Hailstone.rakumod</syntaxhighlight>
{{out}}
<pre>hailstone(27) = 27 82 41 124 [...] 8 4 2 1</pre>
 
It can then be used with a program such as:
<syntaxhighlight lang="raku" line>use Hailstone;
my %score;
(1 .. 100_000).race.map: { %score{hailstone($_).elems}++ };
say "Most common length is {.key}, occurring {.value} times." given max :by(*.value), %score;</syntaxhighlight>
 
Called with a command line as:
<pre>$ RAKULIB=. raku test-hailstone.raku</pre>
 
The environment variable RAKULIB might be necessary if the file Hailstone.rakumod is not in the standard library path for Raku.
 
=={{header|REXX}}==
===task 1===
The following REXX subroutine (or function, as it returns a value) is normally stored in a folder that the REXX interpreter searches first for subroutine/function call/invokes.
is normally stored in a folder that the REXX interpreter
<br>If not there, the REXX interpreter normally checks the current drive (or default disk), and then through some sort of heirarchy --- depending upon the particular REXX interpreter and operating system.
searches first for subroutine/function call/invokes.
<br><br>On Microsoft Windows systems using Regina, PC/REXX, Personal REXX, R4, or ROO, the program name is normally the function name with a file extension of '''REX'' &nbsp; (but that isn't a strict requirement or rule, each REXX interpreter has multiple file extensions that are supported).
<br>If not there, the REXX interpreter normally checks the
current drive (or default disk), and then through some sort of heirarchy --- depending upon the particular REXX interpreter and operating system.
<br><br>On Microsoft Windows systems using Regina, PC/REXX, Personal REXX, R4, or ROO, the program name is normally the function name with a file extension of '''REX''' &nbsp; (but that isn't a strict requirement or rule, each REXX interpreter has multiple file extensions that are supported).
<br>On VM/CMS systems, the filetype (the file extension) is normally &nbsp; '''EXEC'''. &nbsp; If however, the REXX program was previously '''EXECLOAD'''ed, it may have a different name (identity) assigned to it.
<br>The following program (function) is named: &nbsp; '''HAILSTONE.REX''' &nbsp; (the case doesn't matter for Microsoft Windows systems).
<br>All REXX interpreters support subroutines/functions being on the current drive ('''CD'''), default disk (or MDISK in the case of CMS), or the equivalent.
<langsyntaxhighlight lang="rexx">/*REXX program returns the hailstone (Collatz) sequence for any integer.*/
numeric digits 20 /*ensure enough digits for mult. */
parse arg n 1 s /*N & S assigned to the first arg*/
Line 1,089 ⟶ 1,940:
s=s n /*build a sequence list (append).*/
end /*while*/
return s</langsyntaxhighlight>
 
===task 2, 3===
The following program is named: &nbsp;: '''HAIL_PGM.REX''' &nbsp; and is stored in the current directory.
<langsyntaxhighlight lang="rexx">/*REXX pgm tests a number and a range for hailstone (Collatz) sequences.*/
parse arg x .; if x=='' then x=27 /*get the optional first argument*/
 
Line 1,107 ⟶ 1,959:
 
say '(between 1──►99,999) ' bigJ 'has the longest hailstone sequence:' w
/*stick a fork in it, we're done.*/</langsyntaxhighlight>
{{out}}
'''output'''
<pre>
<pre style="overflow:scroll">
27 has a hailstone sequence of 112 and starts with: 27 82 41 124 and ends with: 8 4 2 1
 
Line 1,117 ⟶ 1,969:
===task 4===
The following program is named: &nbsp; '''HAIL_POP.REX''' &nbsp; and is stored in the current directory.
<langsyntaxhighlight lang="rexx">/*REXX pgm finds the most common (popular) hailstone sequence length. */
parse arg z .; if z=='' then z=99999 /*get the optional first argument*/
!.=0
Line 1,131 ⟶ 1,983:
say '(between 1──►'z") " p,
' is the most common hailstone sequence length (with' occ "occurrences)."
/*stick a fork in it, we're done.*/</langsyntaxhighlight>
{{out}}
'''output'''
<pre>
<pre style="overflow:scroll">
(between 1──►99999) 72 is the most common hailstone sequence length (with 1467 occurrences).
</pre>
Line 1,152 ⟶ 2,004:
 
=={{header|Ruby}}==
An executable library checks ''__FILE__ == $0''. Here, ''__FILE__'' is the path of the current source file, and ''$0'' is the path of the current executable. If ''__FILE__ == $0'', then the current source file is the executable, else the current source file is a library for some other executable.
of the current source file, and ''$0'' is the path of the current executable.
If ''__FILE__ == $0'', then the current source file is the executable,
else the current source file is a library for some other executable.
 
* ''__FILE__ == $0'' also works with older versions of Ruby, but this Hailstone example calls new methods in Ruby 1.8.7.
Line 1,160 ⟶ 2,015:
{{works with|Ruby|1.8.7}}
 
<langsyntaxhighlight lang="ruby"># hailstone.rb
module Hailstone
module_function
Line 1,185 ⟶ 2,040:
puts "#{n} has a hailstone sequence length of #{len}"
puts "the largest number in that sequence is #{hailstone(n).max}"
end</langsyntaxhighlight>
 
It runs like any Ruby program:
 
{{out|It runs like any Ruby program}}
<pre>$ ruby scratch.rb
[112, [27, 82, 41, 124], [8, 4, 2, 1]]
Line 1,196 ⟶ 2,050:
This is ''hsfreq.rb'', which requires ''hailstone.rb'' as a library.
 
<langsyntaxhighlight lang="ruby"># hsfreq.rb
require 'hailstone'
 
Line 1,206 ⟶ 2,060:
puts "Given the hailstone sequences from 1 to #{last},"
puts "the most common sequence length is #{length},"
puts "with #{count} such sequences."</langsyntaxhighlight>
 
As with any library, ''hailstone.rb'' must be in <code>$:</code>, the search path for libraries. One way is to leave ''hailstone.rb'' in the current directory and run <code>ruby -I. hsfreq.rb</code>. (Ruby older than 1.9.2 also searches the current directory by default.)
One way is to leave ''hailstone.rb'' in the current directory and run <code>ruby -I. hsfreq.rb</code>.
(Ruby older than 1.9.2 also searches the current directory by default.)
 
<pre>$ ruby -I. hsfreq.rb
Line 1,216 ⟶ 2,072:
 
=={{header|Scala}}==
[[Category:Scala Implementations]]
{{libheader|Scala}}
In Scala it is possible to combine several "main"s (mixed-in by the App trait) in one file (e.g. HailstoneSequence.scala):
(mixed-in by the App trait) in one file (e.g. HailstoneSequence.scala):
<lang Scala>object HailstoneSequence extends App { // Show it all, default number is 27.
<syntaxhighlight lang="scala">
def hailstone(n: Int): Stream[Int] =
object HailstoneSequence extends App { // Show it all, default number is 27.
n #:: (if (n == 1) Stream.empty else hailstone(if (n % 2 == 0) n / 2 else n * 3 + 1))
def hailstone(n: Int): LazyList[Int] =
n #:: (if (n == 1) LazyList.empty else hailstone(if (n % 2 == 0) n / 2 else n * 3 + 1))
 
Hailstone.details(args.headOption.map(_.toInt).getOrElse(27))
Line 1,228 ⟶ 2,085:
 
object Hailstone extends App { // Compute a given or default number to Hailstone sequence
def details(nr: Int): Unit = {
val collatz = HailstoneSequence.hailstone(nr)
 
Line 1,235 ⟶ 2,092:
println(s"It has ${collatz.length} elements.")
}
 
details(args.headOption.map(_.toInt).getOrElse(27))
}
Line 1,243 ⟶ 2,101:
val (n, len) = (1 until 100000).map(n => (n, HailstoneSequence.hailstone(n).length)).maxBy(_._2)
println(s"Longest hailstone sequence length= $len occurring with number $n.")
}
}</lang>
</syntaxhighlight>
 
Steps:
Line 1,272 ⟶ 2,131:
 
C:\Users\FransAdm\Documents></pre>
 
=={{header|Sidef}}==
Library saved as '''Hailstone.sm'''
<syntaxhighlight lang="ruby">func hailstone(n) {
gather {
while (n > 1) {
take(n)
n = (n.is_even ? (n/2) : (take(3*n + 1)/2))
}
take(1)
}
}
 
if (__FILE__ == __MAIN__) { # true when not imported
var seq = hailstone(27)
say "hailstone(27) - #{seq.len} elements: #{seq.first(4)} [...] #{seq.last(4)}"
 
var n = 0
var max = 0
100_000.times { |i|
var seq = hailstone(i)
if (seq.len > max) {
max = seq.len
n = i
}
}
 
say "Longest sequence is for #{n}: #{max}"
}</syntaxhighlight>
 
It can be run with:
<syntaxhighlight lang="shell">$ sidef Hailstone.sm</syntaxhighlight>
 
It can then be used with a program such as:
<syntaxhighlight lang="ruby">include Hailstone
 
var score = Hash()
100_000.times { |i| score{ Hailstone::hailstone(i).len } := 0 ++ }
 
var k = score.keys.max_by {|k| score{k} }
say "Most common length is #{k}, occurring #{score{k}} times"</syntaxhighlight>
 
Called with a command line as:
<syntaxhighlight lang="shell">$ sidef test_hailstone.sf</syntaxhighlight>
 
The library is searched in the directories specified in the '''SIDEF_INC''' environment variable, which defaults to the current directory.
 
=={{header|Tcl}}==
The standard idiom for detecting whether a script is being loaded as a library or run directly is to compare the result of <code>info script</code> (which describes the name of the currently sourced script file) and the global <code>argv0</code> variable (which holds the name of the main script).
<langsyntaxhighlight lang="tcl">### In the file hailstone.tcl ###
package provide hailstone 1.0
 
Line 1,298 ⟶ 2,204:
}
puts "max is $max, with length $maxlen"
}</langsyntaxhighlight>
 
To make the package locatable, run this Tcl script in the same directory which builds the index file:
in the same directory which builds the index file:
<lang tcl>pkg_mkIndex .</lang>
<syntaxhighlight lang="tcl">pkg_mkIndex .</syntaxhighlight>
 
Using the above code as a library then just requires that we tell the script the location of the additional library directory by adding it to the global <code>auto_path</code> variable; it is unnecessary if the script is installed in one of the standard locations (a fairly long list that depends on the installation):
<langsyntaxhighlight lang="tcl">#!/usr/bin/tclsh8.6
package require Tcl 8.6 ;# For [lsort -stride] option
lappend auto_path . ;# Or wherever it is located
Line 1,319 ⟶ 2,226:
lassign $sortedHist mostCommonLength freq
 
puts "most common length is $mostCommonLength, with frequency $freq"</langsyntaxhighlight>
 
=={{omit fromheader|GoWren}}==
 
{{omit from|GUISS}}
In Wren there is no essential difference between the ''main module'' (the module at which the script starts executing) and any ''library module'' which it imports. The latter can also contain executable code and, if it does, it will execute when the library module is imported.
{{omit from|Maxima}}
 
To treat a library module as ''dual purpose'' we therefore need a way to stop its executable code from running when it is being used as a pure library but to let it run otherwise.
 
The strategy here is check whether the main module is the same as the library module and to treat is as executable if it is but as a library otherwise.
 
<syntaxhighlight lang="wren">/* Executable_library.wren */
 
var Hailstone = Fn.new { |n|
if (n < 1) Fiber.abort("Parameter must be a positive integer.")
var h = [n]
while (n != 1) {
n = (n%2 == 0) ? (n/2).floor : 3*n + 1
h.add(n)
}
return h
}
 
var libMain_ = Fn.new {
var h = Hailstone.call(27)
System.print("For the Hailstone sequence starting with n = 27:")
System.print(" Number of elements = %(h.count)")
System.print(" First four elements = %(h[0..3])")
System.print(" Final four elements = %(h[-4..-1])")
 
System.print("\nThe Hailstone sequence for n < 100,000 with the longest length is:")
var longest = 0
var longlen = 0
for (n in 1..99999) {
var h = Hailstone.call(n)
var c = h.count
if (c > longlen) {
longest = n
longlen = c
}
}
System.print(" Longest = %(longest)")
System.print(" Length = %(longlen)")
}
 
// Check if it's being used as a library or not.
import "os" for Process
if (Process.allArguments[1] == "Executable_library.wren") { // if true, not a library
libMain_.call()
}</syntaxhighlight>
 
{{out}}
If we run this directly, we get the expected output:
<pre>
$ wren Executable_library.wren
 
For the Hailstone sequence starting with n = 27:
Number of elements = 112
First four elements = [27, 82, 41, 124]
Final four elements = [8, 4, 2, 1]
 
The Hailstone sequence for n < 100,000 with the longest length is:
Longest = 77031
Length = 351
</pre>
 
If we now create a second module which imports the above and calls its Hailstone function:
<syntaxhighlight lang="wren">/* Executable_library_2.wren */
 
import "./Executable_library" for Hailstone
 
var freq = {}
for (i in 1...100000) {
var len = Hailstone.call(i).count
var f = freq[len]
freq[len] = f ? f + 1 : 1
}
var mk = 0
var mv = 0
for (k in freq.keys) {
var v = freq[k]
if (v > mv) {
mk = k
mv = v
}
}
System.print("The Hailstone length returned most is %(mk), which occurs %(mv) times.")</syntaxhighlight>
 
{{out}}
We can now run this to check that the executable code in hailstone.wren has been suppressed, giving us:
<pre>
$ wren Executable_library_2.wren
 
The Hailstone length returned most is 72, which occurs 1467 times.
</pre>
 
=={{header|zkl}}==
zkl is a system of VM, compiler, etc (ala Python) so no need for compiling/linking etc.
 
File hailstone.zkl:
<syntaxhighlight lang="zkl">fcn collatz(n,z=L()){ z.append(n); if(n==1) return(z);
if(n.isEven) return(self.fcn(n/2,z)); return(self.fcn(n*3+1,z)) }
 
h27:=collatz(27);
println("Hailstone(27)-->",h27[0,4].concat(","),"...",
h27[-4,*].concat(",")," length ",h27.len());
 
[2..0d100_000].pump(Void, // loop n from 2 to 100,000
collatz, // generate Collatz sequence(n)
fcn(c,n){ // if new longest sequence, save length/C, return longest
if(c.len()>n[0]) n.clear(c.len(),c[0]); n}.fp1(L(0,0)))
.println();</syntaxhighlight>
File hailstone2.zkl:
<syntaxhighlight lang="zkl">#!/home/craigd/Bin/zkl
collatz:=Import("hailstone",False,False,False).collatz; // don't run constructor
d:=Dictionary();
[2..0d100_000].pump(Void, // loop n from 2 to 100,000
collatz, // generate Collatz sequence(n)
'wrap(c){ d.incV(c.len()) } // save length
);
println("Number of different lengths: ",d.len());
longest:=(0).max(d.values);
mostFreqLen:=d.filter1('wrap([(k,v)]){ v==longest })[0];
println("Most frequent length: %d; %d sequences of that length."
.fmt(mostFreqLen,longest));</syntaxhighlight>
{{out}}
<pre>
$ zkl hailstone
Hailstone(27)-->27,82,41,124...8,4,2,1 length 112
L(351,77031)
 
$ ./hailstone2.zkl
Number of different lengths: 314
Most frequent length: 72; 1467 sequences of that length.
 
$
</pre>
9,476

edits