(() => {
    'use strict';

    // ------------------ HUMBLE NUMBERS -------------------

    // humbles :: () -> [Int]
    function* humbles() {
        // A non-finite stream of Humble numbers.
        // OEIS A002473
        const hs = new Set([1]);
        while (true) {
            let nxt = Math.min(...hs)
            yield nxt;
            hs.delete(nxt);
            [2, 3, 5, 7].forEach(
                x => hs.add(nxt * x)
            );
        }
    };

    // ----------------------- TEST ------------------------
    // main :: IO ()
    const main = () => {
        console.log('First 50 humble numbers:\n')
        chunksOf(10)(take(50)(humbles())).forEach(
            row => console.log(
                concat(row.map(compose(justifyRight(4)(' '), str)))
            )
        );
        console.log(
            '\nCounts of humble numbers of given digit lengths:'
        );
        const
            counts = map(length)(
                group(takeWhileGen(x => 11 > x)(
                    fmapGen(x => str(x).length)(
                        humbles()
                    )
                ))
            );
        console.log(
            fTable('\n')(str)(str)(
                i => counts[i - 1]
            )(enumFromTo(1)(10))
        );
    };

    // ----------------- GENERIC FUNCTIONS -----------------

    // chunksOf :: Int -> [a] -> [[a]]
    const chunksOf = n =>
        xs => enumFromThenTo(0)(n)(
            xs.length - 1
        ).reduce(
            (a, i) => a.concat([xs.slice(i, (n + i))]),
            []
        );

    // compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
    const compose = (...fs) =>
        // A function defined by the right-to-left
        // composition of all the functions in fs.
        fs.reduce(
            (f, g) => x => f(g(x)),
            x => x
        );

    // concat :: [[a]] -> [a]
    // concat :: [String] -> String
    const concat = xs =>
        0 < xs.length ? (() => {
            const unit = 'string' !== typeof xs[0] ? (
                []
            ) : '';
            return unit.concat.apply(unit, xs);
        })() : [];

    // enumFromThenTo :: Int -> Int -> Int -> [Int]
    const enumFromThenTo = x1 =>
        x2 => y => {
            const d = x2 - x1;
            return Array.from({
                length: Math.floor(y - x2) / d + 2
            }, (_, i) => x1 + (d * i));
        };

    // enumFromTo :: Int -> Int -> [Int]
    const enumFromTo = m =>
        n => Array.from({
            length: 1 + n - m
        }, (_, i) => m + i);

    // fTable :: String -> (a -> String) -> (b -> String)
    //                      -> (a -> b) -> [a] -> String
    const fTable = s => xShow => fxShow => f => xs => {
        // Heading -> x display function ->
        //           fx display function ->
        //    f -> values -> tabular string
        const
            ys = xs.map(xShow),
            w = Math.max(...ys.map(length));
        return s + '\n' + zipWith(
            a => b => a.padStart(w, ' ') + ' -> ' + b
        )(ys)(
            xs.map(x => fxShow(f(x)))
        ).join('\n');
    };

    // fmapGen <$> :: (a -> b) -> Gen [a] -> Gen [b]
    const fmapGen = f =>
        function*(gen) {
            let v = take(1)(gen);
            while (0 < v.length) {
                yield(f(v[0]))
                v = take(1)(gen)
            }
        };

    // group :: Eq a => [a] -> [[a]]
    const group = xs => {
        // A list of lists, each containing only equal elements,
        // such that the concatenation of these lists is xs.
        const go = xs =>
            0 < xs.length ? (() => {
                const
                    h = xs[0],
                    i = xs.findIndex(x => h !== x);
                return i !== -1 ? (
                    [xs.slice(0, i)].concat(go(xs.slice(i)))
                ) : [xs];
            })() : [];
        const v = go(list(xs));
        return 'string' === typeof xs ? (
            v.map(x => x.join(''))
        ) : v;
    };

    // justifyRight :: Int -> Char -> String -> String
    const justifyRight = n =>
        // The string s, preceded by enough padding (with
        // the character c) to reach the string length n.
        c => s => n > s.length ? (
            s.padStart(n, c)
        ) : s;

    // length :: [a] -> Int
    const length = xs =>
        // Returns Infinity over objects without finite length.
        // This enables zip and zipWith to choose the shorter
        // argument when one is non-finite, like cycle, repeat etc
        (Array.isArray(xs) || 'string' === typeof xs) ? (
            xs.length
        ) : Infinity;

    // list :: StringOrArrayLike b => b -> [a]
    const list = xs =>
        // xs itself, if it is an Array,
        // or an Array derived from xs.
        Array.isArray(xs) ? (
            xs
        ) : Array.from(xs);

    // map :: (a -> b) -> [a] -> [b]
    const map = f =>
        // The list obtained by applying f
        // to each element of xs.
        // (The image of xs under f).
        xs => [...xs].map(f);

    // str :: a -> String
    const str = x =>
        x.toString();

    // take :: Int -> [a] -> [a]
    // take :: Int -> String -> String
    const take = n => xs =>
        'GeneratorFunction' !== xs.constructor.constructor.name ? (
            xs.slice(0, n)
        ) : [].concat.apply([], Array.from({
            length: n
        }, () => {
            const x = xs.next();
            return x.done ? [] : [x.value];
        }));

    // takeWhileGen :: (a -> Bool) -> Gen [a] -> [a]
    const takeWhileGen = p => xs => {
        const ys = [];
        let
            nxt = xs.next(),
            v = nxt.value;
        while (!nxt.done && p(v)) {
            ys.push(v);
            nxt = xs.next();
            v = nxt.value
        }
        return ys;
    };

    // zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
    const zipWith = f =>
        // Use of `take` and `length` here allows zipping with non-finite lists
        // i.e. generators like cycle, repeat, iterate.
        xs => ys => {
            const n = Math.min(length(xs), length(ys));
            return Infinity > n ? (
                (([as, bs]) => Array.from({
                    length: n
                }, (_, i) => f(as[i])(
                    bs[i]
                )))([xs, ys].map(
                    compose(take(n), list)
                ))
            ) : zipWithGen(f)(xs)(ys);
        };

    // MAIN ---
    return main();
})();


package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"regexp"
	"strings"
)

func main() {
	f, err := os.Open("unixdict.txt")
	if err != nil {
		log.Fatalln(err)
	}
	defer f.Close()

	s := bufio.NewScanner(f)
	rie := regexp.MustCompile("^ie|[^c]ie")
	rei := regexp.MustCompile("^ei|[^c]ei")
	var cie, ie int
	var cei, ei int
	for s.Scan() {
		line := s.Text()
		if strings.Contains(line, "cie") {
			cie++
		}
		if strings.Contains(line, "cei") {
			cei++
		}
		if rie.MatchString(line) {
			ie++
		}
		if rei.MatchString(line) {
			ei++
		}
	}
	err = s.Err()
	if err != nil {
		log.Fatalln(err)
	}

	if check(ie, ei, "I before E when not preceded by C") &&
		check(cei, cie, "E before I when preceded by C") {
		fmt.Println("Both plausable.")
		fmt.Println(`"I before E, except after C" is plausable.`)
	} else {
		fmt.Println("One or both implausable.")
		fmt.Println(`"I before E, except after C" is implausable.`)
	}
}

// check checks if a statement is plausible. Something is plausible if a is more
// than two times b.
func check(a, b int, s string) bool {
	switch {
	case a > b*2:
		fmt.Printf("%q is plausible (%d vs %d).\n", s, a, b)
		return true
	case a >= b:
		fmt.Printf("%q is implausible (%d vs %d).\n", s, a, b)
	default:
		fmt.Printf("%q is implausible and contra-indicated (%d vs %d).\n",
			s, a, b)
	}
	return false
}


# Input: a positive integer
# Output: true iff the input is humble
def humble:
  . as $i
  | if   ($i < 2) then true
    elif ($i % 2 == 0) then ($i / 2 | floor) | humble
    elif ($i % 3 == 0) then ($i / 3 | floor) | humble
    elif ($i % 5 == 0) then ($i / 5 | floor) | humble
    elif ($i % 7 == 0) then ($i / 7 | floor) | humble
    else false
    end;

def task($digits; $count):
  {len: 0, i:0, count: 0}
  | until( .len > $digits;
      .i += 1
      | if (.i|humble)
        then .len = (.i | tostring | length)
        | if .len <= $digits
	  then .humble[.len] += 1
          | if .count < $count then .count += 1 | .humbles += [.i] else . end
	  else .
	  end
	else .
	end)

  | "First \($count):", .humbles,
    "Distribution of the number of decimal digits up to \($digits) digits:",
     (.humble | range(1;length) as $i | "  \($i):  \(.[$i])") ;

task(6; 50)


function counthumbledigits(maxdigits, returnsequencelength=50)
    n, count, adjustindex, maxdiff = BigInt(1), 0, BigInt(0), 0
    humble, savesequence = Vector{BigInt}([1]), Vector{BigInt}()
    base2, base3, base5, base7 = 1, 1, 1, 1
    next2, next3, next5, next7 = BigInt(2), BigInt(3), BigInt(5), BigInt(7)
    digitcounts= Dict{Int, Int}(1 => 1)
    while n < BigInt(10)^(maxdigits+1)
        n = min(next2, next3, next5, next7)
        push!(humble, n)
        count += 1
        if count == returnsequencelength
            savesequence = deepcopy(humble[1:returnsequencelength])
        elseif count > 2000000
            popfirst!(humble)
            adjustindex += 1
        end
        placesbase10 = length(string(n))
        if haskey(digitcounts, placesbase10)
            digitcounts[placesbase10] += 1
        else
            digitcounts[placesbase10] = 1
        end
        maxdiff = max(maxdiff, count - base2, count - base3, count - base5, count - base7)
        (next2 <= n) && (next2 = 2 * humble[(base2 += 1) - adjustindex])
        (next3 <= n) && (next3 = 3 * humble[(base3 += 1) - adjustindex])
        (next5 <= n) && (next5 = 5 * humble[(base5 += 1) - adjustindex])
        (next7 <= n) && (next7 = 7 * humble[(base7 += 1) - adjustindex])
    end
    savesequence, digitcounts, count, maxdiff
end

counthumbledigits(3)

@time first120, digitcounts, count, maxdiff = counthumbledigits(99)

println("\nTotal humble numbers counted: $count")
println("Maximum depth between top of array and a multiplier: $maxdiff\n")

println("The first 50 humble numbers are: $first120\n\nDigit counts of humble numbers:")
for ndigits in sort(collect(keys(digitcounts)))[1:end-1]
    println(lpad(digitcounts[ndigits], 10), " have ", lpad(ndigits, 3), " digits.")
end


fun isHumble(i: Int): Boolean {
    if (i <= 1) return true
    if (i % 2 == 0) return isHumble(i / 2)
    if (i % 3 == 0) return isHumble(i / 3)
    if (i % 5 == 0) return isHumble(i / 5)
    if (i % 7 == 0) return isHumble(i / 7)
    return false
}

fun main() {
    val limit: Int = Short.MAX_VALUE.toInt()
    val humble = mutableMapOf<Int, Int>()
    var count = 0
    var num = 1

    while (count < limit) {
        if (isHumble(num)) {
            val str = num.toString()
            val len = str.length
            humble.merge(len, 1) { a, b -> a + b }

            if (count < 50) print("$num ")
            count++
        }
        num++
    }
    println("\n")

    println("Of the first $count humble numbers:")
    num = 1
    while (num < humble.size - 1) {
        if (humble.containsKey(num)) {
            val c = humble[num]
            println("%5d have %2d digits".format(c, num))
            num++
        } else {
            break
        }
    }
}


import Network.HTTP
import Text.Regex.TDFA
import Text.Printf

getWordList :: IO String
getWordList  =  do
    response  <-  simpleHTTP.getRequest$ url
    getResponseBody response
        where url = "http://wiki.puzzlers.org/pub/wordlists/unixdict.txt"

main = do
    words <- getWordList
    putStrLn "Checking Rule 1: \"I before E when not preceded by C\"..."
    let numTrueRule1   =  matchCount (makeRegex "[^c]ie" :: Regex) words
        numFalseRule1  =  matchCount (makeRegex "[^c]ei" :: Regex) words
        rule1Plausible  =  numTrueRule1 > (2*numFalseRule1)
    printf "Rule 1 is correct for %d\n        incorrect for %d\n" numTrueRule1 numFalseRule1
    printf "*** Rule 1 is %splausible.\n" (if rule1Plausible then "" else "im")

    putStrLn "Checking Rule 2: \"E before I when preceded by C\"..."
    let numTrueRule2   =  matchCount (makeRegex "cei" :: Regex) words
        numFalseRule2  =  matchCount (makeRegex "cie" :: Regex) words
        rule2Plausible  =  numTrueRule2 > (2*numFalseRule2)
    printf "Rule 2 is correct for %d\n        incorrect for %d\n" numTrueRule2 numFalseRule2
    printf "*** Rule 2 is %splausible.\n" (if rule2Plausible then "" else "im")


import Utils		# To get the FindFirst class

procedure main(a)
    showCounts := "--showcounts" == !a
    totals := table(0)
    phrases := ["cei","cie","ei","ie"]  # Longer phrases first
    ff := FindFirst(phrases)

    every map(!&input) ?
        while totals[2(tab(ff.locate()), ff.moveMatch(), move(-1))] +:= 1

    eiP := totals["cei"] > 2* totals["cie"]
    ieP := (totals["ie"]+totals["cei"]) > 2* totals["ei"]
    write("phrase is ",((\ieP & \eiP),"plausible")|"not plausible")
    write("ie is ",(\ieP,"plausible")|"not plausible")
    write("ei is ",(\eiP,"plausible")|"not plausible")

    if \showCounts then every write(phrase := !phrases,": ",totals[phrase])
end


function isHumble(n)
    local n2 = math.floor(n)

    if n2 <= 1 then
        return true
    end
    if n2 % 2 == 0 then
        return isHumble(n2 / 2)
    end
    if n2 % 3 == 0 then
        return isHumble(n2 / 3)
    end
    if n2 % 5 == 0 then
        return isHumble(n2 / 5)
    end
    if n2 % 7 == 0 then
        return isHumble(n2 / 7)
    end

    return false
end

function main()
    local limit = 10000
    local humble = {0, 0, 0, 0, 0, 0, 0, 0, 0}
    local count = 0
    local num = 1

    while count < limit do
        if isHumble(num) then
            local buffer = string.format("%d", num)
            local le = string.len(buffer)
            if le > 9 then
                break
            end
            humble[le] = humble[le] + 1

            if count < 50 then
                io.write(num .. " ")
            end
            count = count + 1
        end
        num = num + 1
    end
    print("\n")

    print("Of the first " .. count .. " humble numbers:")
    for num=1,9 do
        print(string.format("%5d have %d digits", humble[num], num))
    end
end

main()


HumbleGenerator[max_] :=
 Sort[[email protected][
    2^i 3^j 5^k 7^m, {i, 0, Log[2, max]}, {j, 0, Log[3, max/2^i]}, {k,
      0, Log[5, max/(2^i 3^j)]}, {m, 0, Log[7, max/(2^i 3^j 5^k)]}]]

{"First 50 Humble Numbers:",
  HumbleGenerator[120],
  "\nDigits\[Rule]Count",
  Rule @@@ Tally[IntegerLength /@ Drop[HumbleGenerator[10^100], -1]] //
    Column} // Column


import java.io.BufferedReader;
import java.io.FileReader;

public class IbeforeE
{
	public static void main(String[] args)
	{
		IbeforeE now=new IbeforeE();
		String wordlist="unixdict.txt";
		if(now.isPlausibleRule(wordlist))
			System.out.println("Rule is plausible.");
		else
			System.out.println("Rule is not plausible.");
	}
	boolean isPlausibleRule(String filename)
	{
		int truecount=0,falsecount=0;
		try
		{
			BufferedReader br=new BufferedReader(new FileReader(filename));
			String word;
			while((word=br.readLine())!=null)
			{
				if(isPlausibleWord(word))
					truecount++;
				else if(isOppPlausibleWord(word))
					falsecount++;
			}
			br.close();
		}
		catch(Exception e)
		{
			System.out.println("Something went horribly wrong: "+e.getMessage());
		}

		System.out.println("Plausible count: "+truecount);
		System.out.println("Implausible count: "+falsecount);
		if(truecount>2*falsecount)
			return true;
		return false;
	}
	boolean isPlausibleWord(String word)
	{
		if(!word.contains("c")&&word.contains("ie"))
			return true;
		else if(word.contains("cei"))
			return true;
		return false;
	}
	boolean isOppPlausibleWord(String word)
	{
		if(!word.contains("c")&&word.contains("ei"))
			return true;
		else if(word.contains("cie"))
			return true;
		return false;
	}
}


import sets, strformat

proc min[T](s: HashSet[T]): T =
  ## Return the minimal value in a set.
  if s.card == 0:
    raise newException(ValueError, "set is empty.")
  result = T.high
  for n in s:
    if n < result: result = n

iterator humbleNumbers(): Positive =
  ## Yield the successive humble numbers.
  var s = [1].toHashSet()
  while true:
    let m = min(s)
    yield m
    s.excl(m)
    for k in [2, 3, 5, 7]: s.incl(k * m)

proc showHumbleNumbers(maxCount: Positive) =
  ## Show the first "maxCount" humble numbers.
  var currCount = 0
  for n in humbleNumbers():
    stdout.write n
    inc currCount
    if currCount == maxCount: break
    stdout.write ' '
  echo ""

proc showHumbleCount(ndigits: Positive) =
  ## Show the number of humble numbers with "n <= ndigits" digits.
  echo "Digits   Count"
  echo "------   -----"
  var currdigits = 1
  var count = 0
  var next = 10   # First number with "currdigits + 1" digits.
  for n in humbleNumbers():
    if n >= next:
      # Number of digits has changed.
      echo &"  {currdigits:2d}     {count:5d}"
      inc currdigits
      if currdigits > ndigits: break
      next *= 10
      count = 1
    else:
      inc count

when isMainModule:
  echo "First 50 humble numbers:"
  showHumbleNumbers(50)
  echo ""
  echo "Count of humble numbers with n digits:"
  showHumbleCount(18)


{$IFDEF FPC}
   {$MODE DELPHI}
   {$OPTIMIZATION ON,ALL}
   {$CODEALIGN proc=32,loop=1}
   {$ALIGN 16}
{$ELSE}
  {$APPTYPE CONSOLE}
{$ENDIF}
uses
  sysutils;
const
  //PlInit(4); <= maxPrimFakCnt+1
  maxPrimFakCnt = 3;//3,7,11 to keep data 8-Byte aligned
  minElemCnt = 10;
type
  tPrimList = array of NativeUint;
  tnumber = extended;
  tpNumber= ^tnumber;
  tElem = record
             n   : tnumber;//ln(prime[0]^Pots[0]*...
             dummy: array[0..5] of byte;//extend extended to 16 byte
             Pots: array[0..maxPrimFakCnt] of word;
           end;
  tpElem  = ^tElem;
  tElems  = array of tElem;
  tElemArr  = array [0..0] of tElem;
  tpElemArr  = ^tElemArr;

  tpFaktorRec = ^tFaktorRec;
  tFaktorRec = record
                 frElems  : tElems;
                 frInsElems: tElems;
                 frAktIdx : NativeUint;
                 frMaxIdx : NativeUint;
                 frPotNo  : NativeUint;
                 frActPot : NativeUint;
                 frNextFr : tpFaktorRec;
                 frActNumb: tElem;
                 frLnPrime: tnumber;
               end;
  tArrFR = array of tFaktorRec;

  //LoE == List of Elements
  function LoEGetNextElement(pFR :tpFaktorRec):tElem;forward;

var
  Pl : tPrimList;
  ActIndex  : NativeUint;
  ArrInsert : tElems;

procedure PlInit(n: integer);
const
 cPl : array[0..11] of byte=(2,3,5,7,11,13,17,19,23,29,31,37);
var
  i : integer;
Begin
  IF n>High(cPl)+1 then
    n := High(cPl)
  else
    IF n < 0 then
      n := 1;
  IF maxPrimFakCnt+1 < n then
  Begin
    writeln(' Need to compile with bigger maxPrimFakCnt ');
    Halt(0);
  end;
  setlength(Pl,n);
  dec(n);
  For i := 0 to n do
    Pl[i] := cPl[i];
end;

procedure AusgabeElem(pElem: tElem;ShowPot:Boolean=false);
var
  i : integer;
Begin
  with pElem do
  Begin
    IF n < 23 then
      write(round(exp(n)),' ')
    else
      write('ln ',n:13:7);
    IF ShowPot then
    Begin
      For i := 0 to maxPrimFakCnt do
        write(' ',PL[i]:2,'^',Pots[i]);
      writeln
    end;
  end;
end;

procedure LoECreate(const Pl: tPrimList;var FA:tArrFR);
var
  i : integer;
Begin
  setlength(ArrInsert,100);
  setlength(FA,Length(PL));
  For i := 0 to High(PL) do
    with FA[i] do
    Begin
      //automatic zeroing
      IF i < High(PL) then
      Begin
        setlength(frElems,minElemCnt);
        setlength(frInsElems,minElemCnt);
        frNextFr := @FA[i+1]
      end
      else
      Begin
        setlength(frElems,2);
        setlength(frInsElems,0);
        frNextFr := NIL;
      end;
      frPotNo  := i;
      frLnPrime:= ln(PL[i]);
      frMaxIdx := 0;
      frAktIdx := 0;
      frActPot := 1;
      With frElems[0] do
      Begin
        n := frLnPrime;
        Pots[i]:= 1;
      end;
      frActNumb := frElems[0];
  end;
  ActIndex := 0;
end;

procedure LoEFree(var FA:tArrFR);
var
  i : integer;
Begin
  For i := High(FA) downto Low(FA) do
    setlength(FA[i].frElems,0);
  setLength(FA,0);
end;

function LoEGetActElem(pFr:tpFaktorRec):tElem;inline;
Begin
  with pFr^ do
    result := frElems[frAktIdx];
end;

function LoEGetActLstNumber(pFr:tpFaktorRec):tpNumber;inline;
Begin
  with pFr^ do
    result := @frElems[frAktIdx].n;
end;

procedure LoEIncInsArr(var a:tElems);
Begin
  setlength(a,Length(a)*8 div 5);
end;

procedure LoEIncreaseElems(pFr:tpFaktorRec;minCnt:NativeUint);
var
  newLen: NativeUint;
Begin
  with pFR^ do
  begin
    newLen := Length(frElems);
    minCnt := minCnt+frMaxIdx;
    repeat
      newLen := newLen*8 div 5 +1;
    until newLen > minCnt;
    setlength(frElems,newLen);
  end;
end;

procedure LoEInsertNext(pFr:tpFaktorRec;Limit:tnumber);
var
  pNum : tpNumber;
  pElems : tpElemArr;
  cnt,i,u : NativeInt;
begin
  with pFr^ do
  Begin
    //collect numbers of heigher primes
    cnt := 0;
    pNum := LoEGetActLstNumber(frNextFr);
    while Limit > pNum^ do
    Begin
      frInsElems[cnt] := LoEGetNextElement(frNextFr);
      inc(cnt);
      IF cnt > High(frInsElems) then
        LoEIncInsArr(frInsElems);
      pNum := LoEGetActLstNumber(frNextFr);
    end;

    if cnt = 0 then
     EXIT;

    i := frMaxIdx;
    u := frMaxIdx+cnt+1;

    IF u > High(frElems) then
      LoEIncreaseElems(pFr,cnt);

    IF frPotNo =  0 then
      inc(ActIndex,u);
    //Merge
    pElems := @frElems[0];
    dec(cnt);
    dec(u);
    frMaxIdx:= u;
    repeat
      IF pElems^[i].n < frInsElems[cnt].n then
      Begin
        pElems^[u] := frInsElems[cnt];
        dec(cnt);
      end
      else
      Begin
        pElems^[u] := pElems^[i];
        dec(i);
      end;
      dec(u);
    until (i<0) or (cnt<0);
    IF i < 0 then
      For u := cnt downto 0 do
        pElems^[u] := frInsElems[u];
  end;
end;

procedure LoEAppendNext(pFr:tpFaktorRec;Limit:tnumber);
var
  pNum : tpNumber;
  pElems : tpElemArr;
  i : NativeInt;
begin
  with pFr^ do
  Begin
    i := frMaxIdx+1;
    pElems := @frElems[0];
    pNum := LoEGetActLstNumber(frNextFr);
    while Limit > pNum^ do
    Begin
      IF i > High(frElems) then
      Begin
        LoEIncreaseElems(pFr,10);
        pElems := @frElems[0];
      end;
      pElems^[i] := LoEGetNextElement(frNextFr);
      inc(i);
      pNum := LoEGetActLstNumber(frNextFr);
    end;
    inc(ActIndex,i);
    frMaxIdx:= i-1;
  end;
end;

procedure LoENextList(pFr:tpFaktorRec);
var
  pElems : tpElemArr;
  j,PotNum : NativeInt;
  lnPrime : tnumber;
begin
  with pFR^ do
  Begin
    //increase all Elements by factor
    pElems := @frElems[0];
    LnPrime := frLnPrime;
    PotNum := frPotNo;
    for j := frMaxIdx Downto 0 do
      with pElems^[j] do
      Begin
        n := LnPrime+n;
        inc(Pots[PotNum]);
      end;
    //x^j -> x^(j+1)
    j := frActPot+1;
    with frActNumb do
    begin
      n:= j*LnPrime;
      Pots[PotNum]:= j;
    end;
    frActPot := j;
    //if something follows
    IF frNextFr <> NIL then
      LoEInsertNext(pFR,frActNumb.n);
    frAktIdx := 0;
  end;
end;

function LoEGetNextElementPointer(pFR :tpFaktorRec):tpElem;
Begin
  with pFr^ do
  Begin
    IF frMaxIdx < frAktIdx then
      LoENextList(pFr);
    result := @frElems[frAktIdx];
    inc(frAktIdx);
    inc(ActIndex);
  end;
end;

function LoEGetNextElement(pFR :tpFaktorRec):tElem;
Begin
  with pFr^ do
  Begin
    result := frElems[frAktIdx];
    inc(frAktIdx);
    IF frMaxIdx < frAktIdx then
      LoENextList(pFr);
    inc(ActIndex);
  end;
end;

function LoEGetNextNumber(pFR :tpFaktorRec):tNumber;
Begin
  with pFr^ do
  Begin
    result := frElems[frAktIdx].n;
    inc(frAktIdx);
    IF frMaxIdx < frAktIdx then
      LoENextList(pFr);
    inc(ActIndex);
  end;
end;

procedure LoEGetNumber(pFR :tpFaktorRec;no:NativeUint);
Begin
  dec(no);
  while ActIndex < no do
    LoENextList(pFR);
  with pFr^ do
    frAktIdx := (no-(ActIndex-frMaxIdx)-1);
end;

procedure first50;
var
  FA: tArrFR;
  i : integer;
Begin
  LoECreate(Pl,FA);
  write(1,' ');
  For i := 1 to 49 do
    AusgabeElem(LoEGetNextElement(@FA[0]));
  writeln;
  LoEFree(FA);
end;

procedure GetDigitCounts(MaxDigit:Uint32);
var
  T1,T0 : TDateTime;
  FA: tArrFR;
  i,j,LastCnt : NativeUint;
Begin
  T0 := now;
  inc(MaxDigit);
  LoECreate(Pl,FA);
  i := 1;
  j := 0;
  writeln('Digits   count    total count ');
  repeat
    LastCnt := j;
    repeat
      inc(j);
      with LoEGetNextElementPointer(@FA[0])^ do
        IF (Pots[2]= i) AND (Pots[0]= i) then
          break;
    until false;
    writeln(i:4,j-LastCnt:12,j:15,(now-T0)*86.6e3:10:3,' s');
    LastCnt := j;
    inc(i);
  until i = MaxDigit;
  LoEFree(FA);
  T1 := now;
  writeln('Total number of humble numbers found: ',j);
  writeln('Running time: ',(T1-T0)*86.6e6:0:0,' ms');
end;

Begin
  //check if PlInit(4); <= maxPrimFakCnt+1
  PlInit(4);// 3 -> 2,3,5/ 4  -> 2,3,5,7
  first50;
  GetDigitCounts(100);
End.


def plausibility_ratio: 2;

# scan/2 produces a stream of matches but the first match of a segment (e.g. cie)
# blocks further matches with that segment, and therefore if scan produces "ie",
# it was NOT preceded by "c".
def dictionary:
  reduce .[] as $word
    ( {};
      reduce ($word | scan("ie|ei|cie|cei")) as $found ( .; .[$found] += 1 ));

def rules:
  { "I before E when not preceded by C": ["ie",  "ei"],
    "E before I when preceded by C":     ["cei", "cie"]
   };

# Round to nearest integer or else "round-up"
def round:
  if . < 0 then (-1 * ((- .) | round) | if . == -0 then 0 else . end)
  else floor as $x | if (. - $x) < 0.5 then $x else $x+1 end
  end;

def assess:
  (split("\n") | dictionary) as $dictionary
  | rules as $rules
  | ($rules | keys[]) as $key
  | $rules[$key] as $fragments
  | $dictionary[$fragments[0]] as $x
  | $dictionary[$fragments[1]] as $y
  | ($x / $y) as $ratio
  | (if $ratio > plausibility_ratio then "plausible"
     else "implausible" end) as $plausibility
  | " -- the rule \"\($key)\" is \($plausibility)
    as ratio = \($x)/\($y) ~ \($ratio * 100 |round)%"  ;

"Using the problematic criterion specified in the task requirements:", assess


# v0.0.6

open("unixdict.txt") do txtfile
    rule1, notrule1, rule2, notrule2 = 0, 0, 0, 0
    for word in eachline(txtfile)
        # "I before E when not preceded by C"
        if ismatch(r"ie"i, word)
            if ismatch(r"cie"i, word)
                notrule1 += 1
            else
                rule1 += 1
            end
        end
        # "E before I when preceded by C"
        if ismatch(r"ei"i, word)
            if ismatch(r"cei"i, word)
                rule2 += 1
            else
                notrule2 += 1
            end
        end
    end

    print("Plausibility of \"I before E when not preceded by C\": ")
    println(rule1 > 2 * notrule1 ? "PLAUSIBLE" : "UNPLAUSIBLE")
    print("Plausibility of \"E before I when preceded by C\":")
    println(rule2 > 2 * notrule2 ? "PLAUSIBLE" : "UNPLAUSIBLE")
end


// version 1.0.6

import java.net.URL
import java.io.InputStreamReader
import java.io.BufferedReader

fun isPlausible(n1: Int, n2: Int) = n1 > 2 * n2

fun printResults(source: String, counts: IntArray) {
    println("Results for $source")
    println("  i before e except after c")
    println("    for     ${counts[0]}")
    println("    against ${counts[1]}")
    val plausible1 = isPlausible(counts[0], counts[1])
    println("  sub-rule is${if (plausible1) "" else " not"} plausible\n")
    println("  e before i when preceded by c")
    println("    for     ${counts[2]}")
    println("    against ${counts[3]}")
    val plausible2 = isPlausible(counts[2], counts[3])
    println("  sub-rule is${if (plausible2) "" else " not"} plausible\n")
    val plausible = plausible1 && plausible2
    println("  rule is${if (plausible) "" else " not"} plausible")
}

fun main(args: Array<String>) {
    val url = URL("http://wiki.puzzlers.org/pub/wordlists/unixdict.txt")
    val isr = InputStreamReader(url.openStream())
    val reader = BufferedReader(isr)
    val regexes = arrayOf(
        Regex("(^|[^c])ie"),     // i before e when not preceded by c (includes words starting with ie)
        Regex("(^|[^c])ei"),     // e before i when not preceded by c (includes words starting with ei)
        Regex("cei"),            // e before i when preceded by c
        Regex("cie")             // i before e when preceded by c
    )
    val counts = IntArray(4) // corresponding counts of occurrences
    var word = reader.readLine()
    while (word != null) {
        for (i in 0..3) counts[i] += regexes[i].findAll(word).toList().size
        word = reader.readLine()
    }
    reader.close()
    printResults("unixdict.txt", counts)

    val url2 = URL("http://ucrel.lancs.ac.uk/bncfreq/lists/1_2_all_freq.txt")
    val isr2 = InputStreamReader(url2.openStream())
    val reader2 = BufferedReader(isr2)
    val counts2 = IntArray(4)
    reader2.readLine() // read header line
    var line = reader2.readLine() // read first line and store it
    var words: List<String>
    val splitter = Regex("""(\t+|\s+)""")
    while (line != null) {
        words = line.split(splitter)
        if (words.size == 4)  // first element is empty
            for (i in 0..3) counts2[i] += regexes[i].findAll(words[1]).toList().size * words[3].toInt()
        line = reader2.readLine()
    }
    reader2.close()
    println()
    printResults("British National Corpus", counts2)
}


use strict;
use warnings;
use List::Util 'min';

#use bigint     # works, but slow
use Math::GMPz; # this module gives roughly 16x speed-up

sub humble_gen {
    my @s = ([1], [1], [1], [1]);
    my @m = (2, 3, 5, 7);
    @m = map { Math::GMPz->new($_) } @m; # comment out to NOT use Math::GMPz

    return sub {
    my $n = min $s[0][0], $s[1][0], $s[2][0], $s[3][0];
    for (0..3) {
            shift @{$s[$_]} if $s[$_][0] == $n;
            push @{$s[$_]}, $n * $m[$_]
        }
        return $n
    }
}

my $h = humble_gen;
my $i = 0;
my $upto = 50;

my $list;
++$i, $list .= $h->(). " " until $i == $upto;
print "$list\n";

$h = humble_gen; # from the top...
my $count  = 0;
my $digits = 1;

while ($digits <= $upto) {
    ++$count and next if $digits == length $h->();
    printf "Digits: %2d - Count: %s\n", $digits++, $count;
    $count = 1;
}


local(cie,cei,ie,ei) = (:0,0,0,0)

local(match_ie) = regExp(`[^c]ie`)
local(match_ei) = regExp(`[^c]ei`)

with word in include_url(`http://wiki.puzzlers.org/pub/wordlists/unixdict.txt`)->asString->split("\n")
where #word >> `ie` or #word >> `ei`
do {
    #word >> `cie`
        ? #cie++
    #word >> `cei`
        ? #cei++

    #match_ie->reset(-input=#word, -ignoreCase)&find
        ? #ie++
    #match_ei->reset(-input=#word, -ignoreCase)&find
        ? #ei++
}

local(ie_plausible)  = (#ie  >= (2 * #ei))
local(cei_plausible) = (#cei >= (2 * #cie))

stdoutnl(
    `The rule "I before E when not preceded by C" is ` +
    (#ie_plausible ? '' | 'NOT-') + `PLAUSIBLE. There were ` +
    #ie + ` examples and ` + #ei + ` counter-examples.`
)
stdoutnl(
    `The rule "E before I when preceded by C" is ` +
    (#cei_plausible ? `` | `NOT-`) + `PLAUSIBLE. There were ` +
    #cei + ` examples and ` + #cie + ` counter-examples.`
)
stdoutnl(`Overall the rule is ` + (#ie_plausible and #cei_plausible ? `` | `NOT-`) + `PLAUSIBLE`)


-- Needed to get dictionary file from web server
local http = require("socket.http")

-- Return count of words that contain pattern
function count (pattern, wordList)
    local total = 0
    for word in wordList:gmatch("%S+") do
        if word:match(pattern) then total = total + 1 end
    end
    return total
end

-- Check plausibility of case given its opposite
function plaus (case, opposite, words)
    if count(case, words) > 2 * count(opposite, words) then
        print("PLAUSIBLE")
        return true
    else
        print("IMPLAUSIBLE")
        return false
    end
end

-- Main procedure
local page = http.request("http://wiki.puzzlers.org/pub/wordlists/unixdict.txt")
io.write("I before E when not preceded by C: ")
local sub1 = plaus("[^c]ie", "cie", page)
io.write("E before I when preceded by C: ")
local sub2 = plaus("cei", "[^c]ei", page)
io.write("Overall the phrase is ")
if not (sub1 and sub2) then io.write("not ") end
print("plausible.")


-- demo/rosetta/humble.exw
with javascript_semantics
include mpfr.e

procedure humble(integer n, bool countdigits=false)
-- if countdigits is false: show first n humble numbers,
-- if countdigits is true: count them up to n digits.
    sequence humble = {mpz_init(1)},
             nexts = {2,3,5,7},
             indices = repeat(1,4)
    for i=1 to 4 do nexts[i] = mpz_init(nexts[i]) end for
    integer digits = 1,
            count = 1,
            dead = 1,
            tc = 0
    atom t0 = time()
    mpz p10 = mpz_init(10)
    while ((not countdigits) and length(humble)<n)
       or (countdigits and digits<=n) do
        mpz x = mpz_init_set(mpz_min(nexts))
        humble = append(humble,x)
        if countdigits then
            if mpz_cmp(x,p10)>=0 then
                mpz_mul_si(p10,p10,10)
                integer d = min(indices)
                for k=dead to d-1 do
                    humble[k] = mpz_free(humble[k])
                end for
                dead = d
                string s = iff(digits=1?"":"s"),
                       e = elapsed(time()-t0)
                tc += count
--              e &= sprintf(", %,d dead",{dead-1})
                e &= sprintf(", total:%,d",{tc})
                printf(1,"%,12d humble numbers have %d digit%s (%s)\n",{count,digits,s,e})
                digits += 1
                count = 1
            else
                count += 1
            end if
        end if
        for j=1 to 4 do
            if mpz_cmp(nexts[j],x)<=0 then
                indices[j] += 1
                mpz_mul_si(nexts[j],humble[indices[j]],get_prime(j))
            end if
        end for
    end while
    if not countdigits then
        for i=1 to length(humble) do
            humble[i] = shorten(mpz_get_str(humble[i]),ml:=10)
        end for
        printf(1,"First %d humble numbers: %s\n\n",{n,join(humble," ")})
    end if
end procedure

humble(50)
humble(42,true)


words:= HTTP:-Get("http://wiki.puzzlers.org/pub/wordlists/unixdict.txt"):
lst := StringTools:-Split(words[2],"\n"):
xie, cie, cei, xei := 0, 0, 0, 0:
for item in lst do
	if searchtext("ie", item) <> 0 then
		if searchtext("cie", item) <> 0 then
			cie := cie + 1:
		else
			xie := xie + 1:
		fi:
	fi:
	if searchtext("ei", item) <> 0 then
		if searchtext("cei", item) <> 0 then
			cei := cei + 1:
		else
			xei := xei + 1:
		fi:
	fi:
od:
p1, p2 := evalb(xie > 2*xei),evalb(cei > 2*cie);
printf("The first phrase is %s with supporting features %d, anti features %d\n", piecewise(p1, "plausible", "not plausible"), xie, xei);
printf("The seond phrase is %s with supporting features %d, anti features %d\n", piecewise(p2, "plausible", "not plausible"), cei, cie);
printf("The overall phrase is %s\n", piecewise(p1 and p2, "plausible", "not plausible")):


wordlist =
  Import["http://wiki.puzzlers.org/pub/wordlists/unixdict.txt",
   "Words"];
Print["The number of words in unixdict.txt = " <>
  ToString[Length[wordlist]]]
StringMatchQ[#, ___ ~~ "c" ~~ "i" ~~ "e" ~~ ___] & /@ wordlist ;
cie = Count[%, True];
StringMatchQ[#, ___ ~~ "c" ~~ "e" ~~ "i" ~~ ___] & /@ wordlist ;
cei = Count[%, True];
StringMatchQ[#, ___ ~~ "i" ~~ "e" ~~ ___] & /@ wordlist ;
ie = Count[%, True] - cie;
StringMatchQ[#, ___ ~~ "e" ~~ "i" ~~ ___] & /@ wordlist ;
ei = Count[%, True] - cei;
test1 = ie > 2 ei;
Print["The rule \"I before E when not preceded by C\" is " <>
  If[test1, "PLAUSIBLE", "NOT PLAUSIBLE"]]
Print["There were " <> ToString[ie] <> " examples and " <>
  ToString[ei]  <> " counter examples, for a ratio of " <>
  ToString[N[ie/ei]]]
test2 = cei > 2 cie;
Print["The rule \"E before I when preceded by C\" is " <>
  If[test2, "PLAUSIBLE", "NOT PLAUSIBLE"]]
Print["There were " <> ToString[cei] <> " examples and " <>
  ToString[cie]  <> " counter examples, for a ratio of " <>
  ToString[N[cei/cie]]]
Print["Overall the rule is " <>
  If[test1 && test2, "PLAUSIBLE", "NOT PLAUSIBLE" ]]


function i_before_e_except_after_c(f)

fid = fopen(f,'r');
nei = 0;
cei = 0;
nie = 0;
cie = 0;
while ~feof(fid)
	c = strsplit(strtrim(fgetl(fid)),char([9,32]));
	if length(c) > 2,
		n = str2num(c{3});
	else
		n = 1;
	end;
	if strfind(c{1},'ei')>1, nei=nei+n; end;
	if strfind(c{1},'cei'),  cei=cei+n; end;
	if strfind(c{1},'ie')>1, nie=nie+n; end;
	if strfind(c{1},'cie'),  cie=cie+n; end;
end;
fclose(fid);

printf('cie: %i\nnie: %i\ncei: %i\nnei: %i\n',cie,nie-cie,cei,nei-cei);
v = '';
if (nie < 3 * cie)
	v=' not';
end
printf('I before E when not preceded by C: is%s plausible\n',v);
v = '';
if (nei > 3 * cei)
	v=' not';
end
printf('E before I when preceded by C: is%s plausible\n',v);


100H: /* FIND SOME HUMBLE NUMBERS - NUMBERS WITH NO PRIME FACTORS ABOVE 7 */
   BDOS: PROCEDURE( FN, ARG ); /* CP/M BDOS SYSTEM CALL */
      DECLARE FN BYTE, ARG ADDRESS;
      GOTO 5;
   END BDOS;
   PRINT$CHAR:   PROCEDURE( C ); DECLARE C BYTE;    CALL BDOS( 2, C ); END;
   PRINT$STRING: PROCEDURE( S ); DECLARE S ADDRESS; CALL BDOS( 9, S ); END;
   PRINT$NL:     PROCEDURE; CALL PRINT$STRING( .( 0DH, 0AH, '$' ) );   END;
   PRINT$NUMBER: PROCEDURE( N );
      DECLARE N ADDRESS;
      DECLARE V ADDRESS, N$STR( 6 ) BYTE, W BYTE;
      V = N;
      W = LAST( N$STR );
      N$STR( W ) = '$';
      N$STR( W := W - 1 ) = '0' + ( V MOD 10 );
      DO WHILE( ( V := V / 10 ) > 0 );
         N$STR( W := W - 1 ) = '0' + ( V MOD 10 );
      END;
      CALL PRINT$STRING( .N$STR( W ) );
   END PRINT$NUMBER;
   MIN: PROCEDURE( A, B ) ADDRESS;
      DECLARE  ( A, B ) ADDRESS;
      IF A < B THEN RETURN( A ); ELSE RETURN( B );
   END MIN;
   /* DISPLAY A STASTIC ABOUT HUMBLE NUMBERS */
   PRINT$H$STAT: PROCEDURE( S, D );
      DECLARE ( S, D ) ADDRESS;
      CALL PRINT$STRING( .'THERE ARE $' );
      IF S <  10 THEN CALL PRINT$CHAR( ' ' );
      IF S < 100 THEN CALL PRINT$CHAR( ' ' );
      CALL PRINT$NUMBER( S );
      CALL PRINT$STRING( .' HUMBLE NUMBERS WITH $' );
      CALL PRINT$NUMBER( D );
      CALL PRINT$STRING( .' DIGIT$' );
      IF D > 1 THEN CALL PRINT$CHAR( 'S' );
      CALL PRINT$NL;
   END PRINT$H$STAT;
   /* FIND AND PRINT HUMBLE NUMBERS */
   DECLARE MAX$HUMBLE LITERALLY '400';
   DECLARE H( MAX$HUMBLE ) ADDRESS;
   DECLARE ( P2, P3, P5, P7, M
           , LAST2, LAST3, LAST5, LAST7
           , H1, H2, H3, H4, H5, H6, HPOS
           ) ADDRESS;
   /* 1 IS THE FIRST HUMBLE NUMBER */
   H( 0 ) = 1;
   H1    = 0; H2    = 0; H3    = 0; H4 = 0; H5 = 0; H6 = 0;
   LAST2 = 0; LAST3 = 0; LAST5 = 0; LAST7 = 0;
   P2    = 2; P3    = 3; P5    = 5; P7    = 7;
   DO HPOS = 1 TO MAX$HUMBLE - 1;
      /* THE NEXT HUMBLE NUMBER IS THE LOWEST OF THE NEXT MULTIPLES OF */
      /* 2, 3, 5, 7  */
      M = MIN( MIN( MIN( P2, P3 ), P5 ), P7 );
      H( HPOS ) = M;
      IF M = P2 THEN P2 = 2 * H( LAST2 := LAST2 + 1 );
      IF M = P3 THEN P3 = 3 * H( LAST3 := LAST3 + 1 );
      IF M = P5 THEN P5 = 5 * H( LAST5 := LAST5 + 1 );
      IF M = P7 THEN P7 = 7 * H( LAST7 := LAST7 + 1 );
   END;
   DO HPOS = 0 TO 49;
      CALL PRINT$CHAR( ' ' );
      CALL PRINT$NUMBER( H( HPOS ) );
   END;
   CALL PRINT$NL;
   DO HPOS = 0 TO MAX$HUMBLE - 1;
      M = H( HPOS );
      IF      M <    10 THEN H1 = H1 + 1;
      ELSE IF M <   100 THEN H2 = H2 + 1;
      ELSE IF M <  1000 THEN H3 = H3 + 1;
      ELSE IF M < 10000 THEN H4 = H4 + 1;
   END;
   CALL PRINT$H$STAT( H1, 1 );
   CALL PRINT$H$STAT( H2, 2 );
   CALL PRINT$H$STAT( H3, 3 );
   CALL PRINT$H$STAT( H4, 4 );
EOF


MODULE IEC;
IMPORT SeqIO;
IMPORT Texts;
FROM InOut IMPORT WriteString, WriteCard, WriteLn;
FROM Strings IMPORT Pos;

VAR words, cie, cei, xie, xei: CARDINAL;
    xie_plausible, cei_plausible: BOOLEAN;

PROCEDURE Classify(word: ARRAY OF CHAR);
    VAR end: CARDINAL;
BEGIN
    INC(words);
    end := Pos("", word);

    IF Pos("ie", word) # end THEN
        IF Pos("cie", word) # end
        THEN INC(cie);
        ELSE INC(xie);
        END;
    ELSIF Pos("ei", word) # end THEN
        IF Pos("cei", word) # end
        THEN INC(cei);
        ELSE INC(xei);
        END;
    END;
END Classify;

PROCEDURE ProcessFile(filename: ARRAY OF CHAR);
    VAR file: SeqIO.FILE;
        dict: Texts.TEXT;
        word: ARRAY [0..63] OF CHAR;
        fs: SeqIO.FileState;
        ts: Texts.TextState;
BEGIN
    fs := SeqIO.Open(file, filename);
    ts := Texts.Connect(dict, file);

    WHILE NOT Texts.EOT(dict) DO
        Texts.ReadLn(dict, word);
        Classify(word);
    END;

    ts := Texts.Disconnect(dict);
    fs := SeqIO.Close(file);
END ProcessFile;

PROCEDURE WriteStat(name: ARRAY OF CHAR; num: CARDINAL);
BEGIN
    WriteString(name);
    WriteString(": ");
    WriteCard(num, 0);
    WriteLn;
END WriteStat;

PROCEDURE Plausible(feature: ARRAY OF CHAR; match, nomatch: CARDINAL): BOOLEAN;
    VAR plausible: BOOLEAN;
BEGIN
    WriteString(feature);
    WriteString(": ");
    plausible := 2 * match > nomatch;
    IF NOT plausible THEN
        WriteString("not ");
    END;
    WriteString("plausible.");
    WriteLn;
    RETURN plausible;
END Plausible;

BEGIN
    words := 0;
    cie := 0;
    cei := 0;
    xie := 0;
    xei := 0;

    ProcessFile("unixdict.txt");
    WriteStat("Amount of words", words);
    WriteStat("CIE", cie);
    WriteStat("xIE", xie);
    WriteStat("CEI", cei);
    WriteStat("xEI", xei);
    WriteLn;

    xie_plausible :=
        Plausible("I before E when not preceded by C", xie, cie);
    cei_plausible :=
        Plausible("E before I when preceded by C", cei, xei);

    WriteString("I before E, except after C: ");
    IF NOT (xie_plausible AND cei_plausible) THEN
        WriteString("not ");
    END;
    WriteString("plausible.");
    WriteLn;
END IEC.


import httpclient, strutils, strformat

const
  Rule1 = "\"I before E when not preceded by C\""
  Rule2 = "\"E before I when preceded by C\""
  Phrase = "\"I before E except after C\""
  PlausibilityText: array[bool, string] = ["not plausible", "plausible"]

proc plausibility(rule: string; count1, count2: int): bool =
  ## Compute, display and return plausibility.
  result = count1 > 2 * count2
  stdout.write &"The rule {rule} is {PlausibilityText[result]}: "
  echo &"there were {count1} examples and {count2} counter-examples."

let client = newHttpClient()

var nie, cie, nei, cei = 0
for word in client.getContent("http://wiki.puzzlers.org/pub/wordlists/unixdict.txt").split():
  if word.contains("ie"):
    if word.contains("cie"):
      inc cie
    else:
      inc nie
  if word.contains("ei"):
    if word.contains("cei"):
      inc cei
    else:
      inc nei

let p1 = plausibility(Rule1, nie, nei)
let p2 = plausibility(Rule2, cei, cie)
echo &"So the phrase {Phrase} is {PlausibilityText[p1 and p2]}."


use HTTP;
use Collection;

class HttpTest {
  function : Main(args : String[]) ~ Nil {
    IsPlausibleRule("http://wiki.puzzlers.org/pub/wordlists/unixdict.txt");
  }

  function : PlausibilityCheck(comment : String, x : Int, y : Int) ~ Bool {
    ratio := x->As(Float) / y->As(Float);
    "  Checking plausibility of: {$comment}"->PrintLine();
    if(x > 2 * y) {
      "    PLAUSIBLE. As we have counts of {$x} vs {$y} words, a ratio of {$ratio} times"->PrintLine();
    }
    else if(x > y) {
      "    IMPLAUSIBLE. As although we have counts of {$x} vs {$y} words, a ratio of {$ratio} times does not make it plausible"->PrintLine();
    }
    else {
      "    IMPLAUSIBLE, probably contra-indicated. As we have counts of {$x} vs {$y} words, a ratio of {$ratio} times"->PrintLine();
    };

    return x > 2 * y;
  }

  function : IsPlausibleRule(url : String) ~ Nil {
    truecount := 0;
    falsecount := 0;

    client := HttpClient->New();
    data := client->Get(url)->Get(0)->As(String);
    data := data->ToLower();
    words := data->Split("\n");

    cie := Count("cie", words);
    cei := Count("cei", words);
    not_c_ie := Count("ie", words) - cie;
    not_c_ei := Count("ei", words) - cei;

    "Checking plausibility of \"I before E except after C\":"->PrintLine();
    if(PlausibilityCheck("I before E when not preceded by C", not_c_ie, not_c_ei) &
        PlausibilityCheck("E before I when preceded by C", cei, cie)) {
      "OVERALL IT IS PLAUSIBLE!"->PrintLine();
    }
    else {
      "OVERALL IT IS IMPLAUSIBLE!"->PrintLine();
      "(To be plausible, one word count must exceed another by 2 times)"->PrintLine();
    };
  }

  function : Count(check: String, words : String[]) ~ Int {
    count := 0;

    each(i : words) {
      if(words[i]->Find(check) > -1) {
        count += 1;
      };
    };

    return count;
  }
}


/* FIND SOME HUMBLE NUMBERS - NUMBERS WITH NO PRIME FACTORS ABOVE 7 */
humble_100H: procedure options                                                  (main);

/* PROGRAM-SPECIFIC %REPLACE STATEMENTS MUST APPEAR BEFORE THE %INCLUDE AS */
/* E.G. THE CP/M PL/I COMPILER DOESN'T LIKE THEM TO FOLLOW PROCEDURES      */
   /* PL/I                                                                      */
      %replace dclhumble by         400;
   /* PL/M */                                                                   /*
      DECLARE  DCLHUMBLE LITERALLY '401';
   /* */

/* PL/I DEFINITIONS                                                             */
%include 'pg.inc';
/* PL/M DEFINITIONS: CP/M BDOS SYSTEM CALL AND CONSOLE I/O ROUTINES, ETC. */    /*
   DECLARE BINARY LITERALLY 'ADDRESS', CHARACTER LITERALLY 'BYTE';
   DECLARE FIXED  LITERALLY ' ',       BIT       LITERALLY 'BYTE';
   DECLARE STATIC LITERALLY ' ',       RETURNS   LITERALLY ' ';
   DECLARE FALSE  LITERALLY '0',       TRUE      LITERALLY '1';
   DECLARE HBOUND LITERALLY 'LAST',    SADDR     LITERALLY '.';
   BDOSF: PROCEDURE( FN, ARG )BYTE;
                               DECLARE FN BYTE, ARG ADDRESS; GOTO 5;   END;
   BDOS: PROCEDURE( FN, ARG ); DECLARE FN BYTE, ARG ADDRESS; GOTO 5;   END;
   PRCHAR:   PROCEDURE( C );   DECLARE C BYTE;      CALL BDOS( 2, C ); END;
   PRSTRING: PROCEDURE( S );   DECLARE S ADDRESS;   CALL BDOS( 9, S ); END;
   PRNL:     PROCEDURE;        CALL PRCHAR( 0DH ); CALL PRCHAR( 0AH ); END;
   PRNUMBER: PROCEDURE( N );
      DECLARE N ADDRESS;
      DECLARE V ADDRESS, N$STR( 6 ) BYTE, W BYTE;
      N$STR( W := LAST( N$STR ) ) = '$';
      N$STR( W := W - 1 ) = '0' + ( ( V := N ) MOD 10 );
      DO WHILE( ( V := V / 10 ) > 0 );
         N$STR( W := W - 1 ) = '0' + ( V MOD 10 );
      END;
      CALL BDOS( 9, .N$STR( W ) );
   END PRNUMBER;
   MODF: PROCEDURE( A, B )ADDRESS;
      DECLARE ( A, B )ADDRESS;
      RETURN( A MOD B );
   END MODF;
   MIN: PROCEDURE( A, B ) ADDRESS;
      DECLARE  ( A, B ) ADDRESS;
      IF A < B THEN RETURN( A ); ELSE RETURN( B );
   END MIN;
/* END LANGUAGE DEFINITIONS */

   /* TASK */

   /* DISPLAY A STASTIC ABOUT HUMBLE NUMBERS */
   PRHUMBLESTAT: PROCEDURE( S, D );
      DECLARE ( S, D ) FIXED BINARY;
      CALL PRSTRING( SADDR( 'THERE ARE $' ) );
      IF S <  10 THEN CALL PRCHAR( ' ' );
      IF S < 100 THEN CALL PRCHAR( ' ' );
      CALL PRNUMBER( S );
      CALL PRSTRING( SADDR( ' HUMBLE NUMBERS WITH $' ) );
      CALL PRNUMBER( D );
      CALL PRSTRING( SADDR( ' DIGIT$' ) );
      IF D > 1 THEN CALL PRCHAR( 'S' );
      CALL PRNL;
   END PRHUMBLESTAT;

   /* FIND AND PRINT HUMBLE NUMBERS */

   DECLARE H( DCLHUMBLE ) FIXED BINARY;
   DECLARE ( P2, P3, P5, P7, M
           , LAST2, LAST3, LAST5, LAST7
           , H1, H2, H3, H4, HPOS
           , MAXHUMBLE
           ) FIXED BINARY;

   MAXHUMBLE = HBOUND( H                                                        ,1
                     );

   /* 1 IS THE FIRST HUMBLE NUMBER */
   H( 1 ) = 1;
   LAST2 = 1; LAST3 = 1; LAST5 = 1; LAST7 = 1;
   P2    = 2; P3    = 3; P5    = 5; P7    = 7;
   DO HPOS = 2 TO MAXHUMBLE;
      /* THE NEXT HUMBLE NUMBER IS THE LOWEST OF THE NEXT MULTIPLES OF */
      /* 2, 3, 5, 7  */
      M = MIN( MIN( MIN( P2, P3 ), P5 ), P7 );
      H( HPOS ) = M;
      IF M = P2 THEN DO; LAST2 = LAST2 + 1; P2 = 2 * H( LAST2 ); END;
      IF M = P3 THEN DO; LAST3 = LAST3 + 1; P3 = 3 * H( LAST3 ); END;
      IF M = P5 THEN DO; LAST5 = LAST5 + 1; P5 = 5 * H( LAST5 ); END;
      IF M = P7 THEN DO; LAST7 = LAST7 + 1; P7 = 7 * H( LAST7 ); END;
   END;

   /* SHOW THE FIRST 50 HUMBLE NUMBERS */
   DO HPOS = 1 TO 50;
      CALL PRCHAR( ' ' );
      M = H( HPOS );
      IF M <  10 THEN CALL PRCHAR( ' ' );
      IF M < 100 THEN CALL PRCHAR( ' ' );
      CALL PRNUMBER( H( HPOS ) );
      IF MODF( HPOS, 16 ) = 0 THEN CALL PRNL;
   END;
   CALL PRNL;

   /* SHOW THE NUMBER OF HUMBLE NUMBERS UP TO VARIOUS POWERS OF 10 */
   H1 = 0; H2 = 0; H3 = 0; H4 = 0;
   DO HPOS = 1 TO MAXHUMBLE;
      M = H( HPOS );
      IF      M <    10 THEN H1 = H1 + 1;
      ELSE IF M <   100 THEN H2 = H2 + 1;
      ELSE IF M <  1000 THEN H3 = H3 + 1;
      ELSE IF M < 10000 THEN H4 = H4 + 1;
   END;

   CALL PRHUMBLESTAT( H1, 1 );
   CALL PRHUMBLESTAT( H2, 2 );
   CALL PRHUMBLESTAT( H3, 3 );
   CALL PRHUMBLESTAT( H4, 4 );

EOF: end humble_100H;


#!/usr/bin/perl
use warnings;
use strict;

sub result {
    my ($support, $against) = @_;
    my $ratio  = sprintf '%.2f', $support / $against;
    my $result = $ratio >= 2;
    print "$support / $against = $ratio. ", 'NOT ' x !$result, "PLAUSIBLE\n";
    return $result;
}

my @keys  = qw(ei cei ie cie);
my %count;

while (<>) {
    for my $k (@keys) {
        $count{$k}++ if -1 != index $_, $k;
    }
}

my ($support, $against, $result);

print 'I before E when not preceded by C: ';
$support = $count{ie} - $count{cie};
$against = $count{ei} - $count{cei};
$result += result($support, $against);

print 'E before I when preceded by C: ';
$support = $count{cei};
$against = $count{cie};
$result += result($support, $against);

print 'Overall: ', 'NOT ' x ($result < 2), "PLAUSIBLE.\n";


-- demo\rosetta\IbeforeE.exw
with javascript_semantics
procedure show_plausibility(string msg, integer w, wo)
    string no = iff(w<2*wo?" not":"")
    printf(1, "%s (pro: %3d, anti: %3d) is%s plausible\n",{msg,w,wo,no})
end procedure

string text = join(unix_dict())
-- Note: my unixdict.txt begins with "10th" and ends with "zygote", so
-- boundary checks such as "i>=2 and i+1<=length(text)" can be skipped.
integer cei=0, xei=0, cie=0, xie=0
for i=1 to length(text) do
    if text[i]='i' then
        if text[i-1]='e' then
            if text[i-2]='c' then
                cei += 1
            else
                xei += 1
            end if
        end if
        -- (nb not elsif here; "eie" occurs twice)
        if text[i+1]='e' then
            if text[i-1]='c' then
                cie += 1
            else
                xie += 1
            end if
        end if
    end if
end for
printf(1,"occurances: cie:%d, xie:%d, cei:%d, xei:%d\n", {cie,xie,cei,xei})
show_plausibility( "i before e except after c", xie, cie );
show_plausibility( "e before i except after c", xei, cei );
show_plausibility( "i before e   when after c", cie, cei );
show_plausibility( "e before i   when after c", cei, cie );
show_plausibility( "i before e     in general", xie + cie, xei + cei );
show_plausibility( "e before i     in general", xei + cei, xie + cie )


'''Humble numbers'''

from itertools import groupby, islice
from functools import reduce

# humbles :: () -> [Int]
def humbles():
    '''A non-finite stream of Humble numbers.
       OEIS A002473
    '''
    hs = set([1])
    while True:
        nxt = min(hs)
        yield nxt
        hs.remove(nxt)
        hs.update(nxt * x for x in [2, 3, 5, 7])

# TEST ----------------------------------------------------
# main :: IO ()
def main():
    '''First 50, and counts with N digits'''

    print('First 50 Humble numbers:\n')
    for row in chunksOf(10)(
            take(50)(humbles())
    ):
        print(' '.join(map(
            lambda x: str(x).rjust(3),
            row
        )))

    print('\nCounts of Humble numbers with n digits:\n')
    for tpl in take(10)(
            (k, len(list(g))) for k, g in
            groupby(len(str(x)) for x in humbles())
    ):
        print(tpl)

# GENERIC -------------------------------------------------

# chunksOf :: Int -> [a] -> [[a]]
def chunksOf(n):
    '''A series of lists of length n, subdividing the
       contents of xs. Where the length of xs is not evenly
       divible, the final list will be shorter than n.
    '''
    return lambda xs: reduce(
        lambda a, i: a + [xs[i:n + i]],
        range(0, len(xs), n), []
    ) if 0 < n else []

# take :: Int -> [a] -> [a]
# take :: Int -> String -> String
def take(n):
    '''The prefix of xs of length n,
       or xs itself if n > length xs.
    '''
    return lambda xs: (
        list(islice(xs, n))
    )

# MAIN ---
if __name__ == '__main__':
    main()


  ' [ 2 3 5 7 ] smoothwith
      [ -1 peek [ 10 12 ** ] constant = ]
  -1 split drop
  dup 50 split drop echo cr cr
  12 times
    [ dup 0 over size
      rot 10 i^ 1+ ** searchwith <
      drop split swap size echo
      sp i^ 1+ echo
      say "-digit humble numbers" cr ]
  drop


main =>
  Words = read_file_lines("unixdict.txt"),
  IEWords = [Word : Word in Words, find(Word,"ie",_,_)],
  EIWords = [Word : Word in Words, find(Word,"ei",_,_)],

  % cie vs not cie
  [CIE_len, CIE_not_len] = partition_len(IEWords,"cie"),
  println([cie=CIE_len,cie_not=CIE_not_len]),

  % cei vs not cei
  [CEI_len, CEI_not_len] = partition_len(EIWords,"cei"),
  println([cei=CEI_len,cei_not=CEI_not_len]),

  nl,
  printf("I before E when not preceeded by C (%d vs %d): %w\n",
                 CIE_not_len,CEI_not_len,plausible(CIE_not_len,CEI_not_len)),
  printf("E before I when preceeded by C (%d cs %d): %w\n",
                 CEI_len,CIE_len,plausible(CEI_len,CIE_len)).

plausible(Len1,Len2) = cond(Len1 / Len2 > 2,"plausible","not plausible").

partition_len(Words,Sub) = [True.len, False.len] =>
  True = [],
  False = [],
  foreach(Word in Words)
    if find(Word,Sub,_,_) then
      True := [Word|True]
    else
      False := [Word|False]
    end
  end.


(de ibEeaC (File . Prg)
   (let
      (Cie (let N 0 (in File (while (from "cie") (run Prg))))
         Nie (let N 0 (in File (while (from "ie") (run Prg))))
         Cei (let N 0 (in File (while (from "cei") (run Prg))))
         Nei (let N 0 (in File (while (from "ei") (run Prg)))) )
      (prinl "cie: " Cie)
      (prinl "nie: " (dec 'Nie Cie))
      (prinl "cei: " Cei)
      (prinl "nei: " (dec 'Nei Cei))
      (let (NotI (> (* 3 Cie) Nie)  NotE (> Nei (* 3 Cei)))
         (prinl
            "I before E except after C: is"
            (and NotI " not")
            " plausible" )
         (prinl
            "E before I when after C: is"
            (and NotE " not")
            " plausible" )
         (prinl
            "Overall rule is"
            (and (or NotI NotE) " not")
            " plausible" ) ) ) )

(ibEeaC "unixdict.txt"
   (inc 'N) )

(prinl)

(ibEeaC "1_2_all_freq.txt"
   (inc 'N (format (stem (line) "\t"))) )


iBeforeE: procedure options(main);
    declare dict file;
    open file(dict) title('unixdict.txt');
    on endfile(dict) go to report;

    declare (cie, xie, cei, xei) fixed;
    declare word char(32) varying;
    cie = 0;
    xie = 0;
    cei = 0;
    xei = 0;
    do while('1'b);
        get file(dict) list(word);
        if index(word, 'ie') ^= 0 then
            if index(word, 'cie') ^= 0 then
                cie = cie + 1;
            else
                xie = xie + 1;
        if index(word, 'ei') ^= 0 then
            if index(word, 'cei') ^= 0 then
                cei = cei + 1;
            else
                xei = xei + 1;

    end;

report:
    close file(dict);
    put skip list('CIE:', cie);
    put skip list('xIE:', xie);
    put skip list('CEI:', cei);
    put skip list('xEI:', xei);

    declare (ieNotC, eiC) bit;
    ieNotC = xie * 2 > cie;
    eiC = cei * 2 > xei;

    put skip list('I before E when not preceded by C:');
    if ^ieNotC then put list('not');
    put list('plausible.');

    put skip list('E before I when preceded by C:');
    if ^eiC then put list('not');
    put list('plausible.');

    put skip list('I before E, except after C:');
    if ^(ieNotC & eiC) then put list('not');
    put list('plausible.');
end iBeforeE;


#lang racket

(define (gen-humble-numbers N (kons #f) (k0 (void)))
  (define rv (make-vector N 1))

  (define (loop n 2-idx 3-idx 5-idx 7-idx next-2 next-3 next-5 next-7 k)
    (if (= n N)
        rv
        (let ((mn (min next-2 next-3 next-5 next-7)))
          (vector-set! rv n mn)
          (define (add-1-if-min n x) (if (= mn n) (add1 x) x))
          (define (*vr.i-if-min n m i) (if (= mn n) (* m (vector-ref rv i)) n))
          (let* ((2-idx  (add-1-if-min next-2 2-idx))
                 (next-2 (*vr.i-if-min next-2 2 2-idx))
                 (3-idx  (add-1-if-min next-3 3-idx))
                 (next-3 (*vr.i-if-min next-3 3 3-idx))
                 (5-idx  (add-1-if-min next-5 5-idx))
                 (next-5 (*vr.i-if-min next-5 5 5-idx))
                 (7-idx  (add-1-if-min next-7 7-idx))
                 (next-7 (*vr.i-if-min next-7 7 7-idx))
                 (k (and kons (kons mn k))))
            (loop (add1 n) 2-idx 3-idx 5-idx 7-idx next-2 next-3 next-5 next-7 k)))))
  (loop 1 0 0 0 0 2 3 5 7 (and kons (kons 1 k0))))

(define ((digit-tracker breaker) h last-ten.count)
  (let ((last-ten (car last-ten.count)))
    (if (< h last-ten)
        (cons last-ten (add1 (cdr last-ten.count)))
        (begin
          (printf "~a humble numbers with ~a digits~%" (cdr last-ten.count) (order-of-magnitude last-ten))
          (cons (breaker (* 10 last-ten)) 1)))))

(define (Humble-numbers)
  (displayln (gen-humble-numbers 50))
  (time
   (let/ec break
     (void (gen-humble-numbers
            100000000
            (digit-tracker (λ (o) (if (> (order-of-magnitude o) 100) (break) o)))
            '(10 . 0))))))

(module+ main
  (Humble-numbers))


sub smooth-numbers (*@list) {
    cache my \Smooth := gather {
        my %i = (flat @list) Z=> (Smooth.iterator for ^@list);
        my %n = (flat @list) Z=> 1 xx *;

        loop {
            take my $n := %n{*}.min;

            for @list -> \k {
                %n{k} = %i{k}.pull-one * k if %n{k} == $n;
            }
        }
    }
}

my $humble := smooth-numbers(2,3,5,7);

put $humble[^50];
say '';

my $upto = 50;
my $digits = 1;
my $count;

$humble.map: -> \h {
    ++$count and next if h.chars == $digits;
    printf "Digits: %2d - Count: %s\n", $digits++, $count;
    $count = 1;
    last if $digits > $upto;
}


$Web = New-Object -TypeName Net.Webclient
$Words = $web.DownloadString('http://wiki.puzzlers.org/pub/wordlists/unixdict.txt')

$IE = $EI = $CIE = $CEI = @()

$Clause1 = $Clause2 = $MainClause = $false

foreach ($Word in $Words.split())
{
    switch ($Word)
    {
        {($_ -like '*ie*') -and ($_ -notlike '*cie*')} {$IE += $Word}
        {($_ -like '*ei*') -and ($_ -notlike '*cei*')} {$EI += $Word}
        {$_ -like '*cei*'} {$CEI += $Word}
        {$_ -like '*cie*'} {$CIE += $Word}
    }
}

if ($IE.count -gt $EI.count * 2)
{$Clause1 = $true}
"The plausibility of 'I before E when not preceded by C' is $Clause1"

if ($CEI.count -gt $CIE.count * 2)
{$Clause2 = $true}
"The plausibility of 'E before I when preceded by C' is $Clause2"

if ($Clause1 -and $Clause2)
{$MainClause = $True}
"The plausibility of the phrase 'I before E except after C' is $MainClause"


If ReadFile(1,GetPathPart(ProgramFilename())+"wordlist(en).txt")
  While Not Eof(1)
    wl$+ReadString(1)+";"
  Wend
  CloseFile(1)
EndIf

OpenConsole()
PrintN("Number of words in [wordlist(en).txt]: "+CountString(wl$,";"))
cei.i=CountString(wl$,"cei") : PrintN("Instances of [cei]                   : "+Str(cei))
cie.i=CountString(wl$,"cie") : PrintN("Instances of [cie]                   : "+Str(cie))
Print("Rule: 'e' before 'i' when preceded by 'c' is = ")
If cei>cie : PrintN("plausible") : Else : PrintN("not plausible") : EndIf
wl$=RemoveString(wl$,"cei")  : wl$=RemoveString(wl$,"cie")
PrintN("")
ei.i=CountString(wl$,"ei")   : PrintN("Instances of [*ei] '*'<>'c'          : "+Str(ei))
ie.i=CountString(wl$,"ie")   : PrintN("Instances of [*ie] '*'<>'c'          : "+Str(ie))
Print("Rule: 'i' before 'e' when not preceded by 'c' is = ")
If ie>ei : PrintN("plausible") : Else : PrintN("not plausible") : EndIf
PrintN("")
Print("Overall the rule is : ")
If cei>cie And ie>ei : PrintN("PLAUSIBLE") : Else : PrintN("NOT PLAUSIBLE") :  EndIf
Input()


/*REXX program computes and displays humble numbers,  also will display counts of sizes.*/
parse arg n m .                                  /*obtain optional arguments from the CL*/
if n=='' | n==","  then n= 50                    /*Not specified?  Then use the default.*/
if m=='' | m==","  then m= 60                    /* "      "         "   "   "     "    */
numeric digits 1 + max(20, m)                    /*be able to handle some big numbers.  */
$.= 0                                            /*a count array for  X  digit humble #s*/
call humble n;                    list=          /*call HUMBLE sub; initialize the list.*/
                  do j=1  for n;  list= list @.j /*append a  humble  number to the list.*/
                  end   /*j*/

if list\=''  then do;    say "A list of the first "    n    ' humble numbers are:'
                         say strip(list)         /*elide the leading blank in the list. */
                  end
say
call humble -m                                   /*invoke subroutine for counting nums. */
if $.1==0  then exit                             /*if no counts, then we're all finished*/
total= 0                                         /*initialize count of humble numbers.  */
$.1= $.1 + 1                                     /*adjust count for absent 1st humble #.*/
say '                    The digit counts of humble numbers:'
say '                 ═════════════════════════════════════════'
        do c=1  while $.c>0;  s= left('s', length($.c)>1)   /*count needs pluralization?*/
        say right( commas($.c), 30)         ' have '         right(c, 2)         " digit"s
        total= total + $.c                       /* ◄─────────────────────────────────┐ */
        end   /*k*/                              /*bump humble number count (so far)──┘ */
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
commas: procedure; arg _;  do i=length(_)-3 to 1 by -3; _=insert(',', _, i); end; return _
/*──────────────────────────────────────────────────────────────────────────────────────*/
humble: procedure expose @. $.;   parse arg x;         if x==0  then return
        y= abs(x);   a= y;        noCount= x>0;        if x<0   then y= 999999999
        #2= 1;    #3= 1;    #5= 1;     #7= 1     /*define the initial humble constants. */
                  $.= 0;    @.= 0;    @.1= 1     /*initialize counts and humble numbers.*/
          do h=2  for y-1
          @.h= min(2*@.#2,3*@.#3,5*@.#5,7*@.#7)  /*pick the minimum of 4 humble numbers.*/
          m= @.h                                 /*M:    "     "     " "    "      "    */
          if 2*@.#2 == m   then #2 = #2 + 1      /*Is number already defined? Use next #*/
          if 3*@.#3 == m   then #3 = #3 + 1      /* "    "      "       "      "    "  "*/
          if 5*@.#5 == m   then #5 = #5 + 1      /* "    "      "       "      "    "  "*/
          if 7*@.#7 == m   then #7 = #7 + 1      /* "    "      "       "      "    "  "*/
          if noCount       then iterate          /*Not counting digits?   Then iterate. */
          L= length(m);    if L>a  then leave    /*Are we done with counting?  Then quit*/
          $.L= $.L + 1                           /*bump the digit count for this number.*/
          end   /*h*/                            /*the humble numbers are in the @ array*/
        return                                   /* "  count  results  "   "  "  $   "  */


import urllib.request
import re

PLAUSIBILITY_RATIO = 2

def plausibility_check(comment, x, y):
    print('\n  Checking plausibility of: %s' % comment)
    if x > PLAUSIBILITY_RATIO * y:
        print('    PLAUSIBLE. As we have counts of %i vs %i, a ratio of %4.1f times'
              % (x, y, x / y))
    else:
        if x > y:
            print('    IMPLAUSIBLE. As although we have counts of %i vs %i, a ratio of %4.1f times does not make it plausible'
                  % (x, y, x / y))
        else:
            print('    IMPLAUSIBLE, probably contra-indicated. As we have counts of %i vs %i, a ratio of %4.1f times'
                  % (x, y, x / y))
    return x > PLAUSIBILITY_RATIO * y

def simple_stats(url='http://wiki.puzzlers.org/pub/wordlists/unixdict.txt'):
    words = urllib.request.urlopen(url).read().decode().lower().split()
    cie = len({word for word in words if 'cie' in word})
    cei = len({word for word in words if 'cei' in word})
    not_c_ie = len({word for word in words if re.search(r'(^ie|[^c]ie)', word)})
    not_c_ei = len({word for word in words if re.search(r'(^ei|[^c]ei)', word)})
    return cei, cie, not_c_ie, not_c_ei

def print_result(cei, cie, not_c_ie, not_c_ei):
    if ( plausibility_check('I before E when not preceded by C', not_c_ie, not_c_ei)
         & plausibility_check('E before I when preceded by C', cei, cie) ):
        print('\nOVERALL IT IS PLAUSIBLE!')
    else:
        print('\nOVERALL IT IS IMPLAUSIBLE!')
    print('(To be plausible, one count must exceed another by %i times)' % PLAUSIBILITY_RATIO)

print('Checking plausibility of "I before E except after C":')
print_result(*simple_stats())


DEFINT A-Z
DIM W AS STRING
CLS
OPEN "I", 1, "UNIXDICT.TXT"
DO
    LINE INPUT #1, W
    IF INSTR(W, "ie") THEN IF INSTR(W, "cie") THEN CI = CI + 1 ELSE XI = XI + 1
    IF INSTR(W, "ei") THEN IF INSTR(W, "cei") THEN CE = CE + 1 ELSE XE = XE + 1
LOOP WHILE NOT EOF(1)
CLOSE #1

PRINT "CIE:"; CI
PRINT "xIE:"; XI
PRINT "CEI:"; CE
PRINT "xEI:"; XE
PRINT
PRINT "I before E when not preceded by C: ";
IF 2 * XI <= CI THEN PRINT "not ";
PRINT "plausible."
PRINT "E before I when preceded by C: ";
IF 2 * CE <= XE THEN PRINT "not ";
PRINT "plausible."


load "stdlib.ring"

limit = 10
numList = []

for n2 = 0 to limit
    for n3 = 0 to limit
        for n5 = 0 to limit
            for n7 = 0 to limit
                num = pow(2,n2) * pow(3,n3) * pow(5,n5) * pow(7,n7)
                add(numList,num)
            next
        next
    next
next

numList = sort(numList)

see "The first 50 Humble numbers: " + nl

for n = 1 to 50
    see "" + numList[n] + " "
next


def humble?(i)
  while i % 2 == 0; i /= 2 end
  while i % 3 == 0; i /= 3 end
  while i % 5 == 0; i /= 5 end
  while i % 7 == 0; i /= 7 end
  i == 1
end

count, num = 0, 0
digits = 10                        # max digits for humble numbers
limit  = 10 ** digits              # max numbers to search through
humble = Array.new(digits + 1, 0)

while (num += 1) < limit
  if humble?(num)
    humble[num.to_s.size] += 1
    print num, " " if count < 50
    count += 1
  end
end

print "\n\nOf the first #{count} humble numbers:\n"
(1..digits).each { |num|  printf("%5d have %2d digits\n", humble[num], num) }


func smooth_generator(primes) {

    var s = primes.len.of { [1] }

    {
        var n = s.map { .first }.min
        { |i|
            s[i].shift if (s[i][0] == n)
            s[i] << (n * primes[i])
        } * primes.len
        n
    }
}

with (smooth_generator([2,3,5,7])) {|g|
    say 50.of { g.run }.join(' ')
}

say "\nThe digit counts of humble numbers"
say '═'*35

with (smooth_generator([2,3,5,7])) {|g|
    for (var(d=1,c=0); d <= 20; ++c) {
        var n = g.run
        n.len > d || next
        say "#{'%10s'%c.commify}  have  #{'%2d'%d}  digit#{[:s,''][d==1]}"
        (c, d) = (0, n.len)
    }
}


words = tolower(readLines("http://wiki.puzzlers.org/pub/wordlists/unixdict.txt"))
ie.npc = sum(grepl("(?<!c)ie", words, perl = T))
ei.npc = sum(grepl("(?<!c)ei", words, perl = T))
ie.pc = sum(grepl("cie", words, fixed = T))
ei.pc = sum(grepl("cei", words, fixed = T))

p1 = ie.npc > 2 * ei.npc
p2 = ei.pc > 2 * ie.pc

message("(1) is ", (if (p1) "" else "not "), "plausible.")
message("(2) is ", (if (p2) "" else "not "), "plausible.")
message("The whole phrase is ", (if (p1 && p2) "" else "not "), "plausible.")


#lang racket

(define (get-tallies filename line-parser . patterns)
  (for/fold ([totals (make-list (length patterns) 0)])
    ([line (file->lines filename)])
    (match-let ([(list word n) (line-parser line)])
      (for/list ([p patterns] [t totals])
        (if (regexp-match? p word)
            (+ n t) t)))))

(define (plausible test) (string-append (if test "" "IM") "PLAUSIBLE"))

(define (subrule description examples counters)
  (let ([result (> examples (* 2 counters))])
    (printf "  The sub-rule \"~a\" is ~a.  There were ~a examples and ~a counter-examples.\n"
            description (plausible result) examples counters)
    result))

(define (plausibility description filename parser)
  (printf "~a:\n" description)
  (match-let ([(list cei cie ie ei) (get-tallies filename parser "cei" "cie" "ie" "ei")])
    (let ([rule1 (subrule "I before E when not preceded by C" (- ie cie) (- ei cei))]
          [rule2 (subrule "E before I when preceded by C" cei cie)])
      (printf "\n  Overall, the rule \"I before E, except after C\" is ~a.\n"
              (plausible (and rule1 rule2))))))

(define (parse-frequency-data line)
  (let ([words (string-split line)])
    (list (string-join (drop-right words 2)) (string->number (last words)))))

(plausibility "Dictionary" "unixdict.txt" (λ (line) (list line 1))) (newline)
(plausibility "Word frequencies (stretch goal)" "1_2_all_freq.txt" parse-frequency-data)


proc humble? x {
   foreach f {2 3 5 7} {
      while {$x % $f == 0} {set x [expr {$x / $f}]}
   }
   return [expr {$x == 1}]
}
set t1 {}
for {set i 1} {[llength $t1] < 50} {incr i} {
   if [humble? $i] {lappend t1 $i}
}
puts $t1


Module Module1

    Function IsHumble(i As Long) As Boolean
        If i <= 1 Then
            Return True
        End If
        If i Mod 2 = 0 Then
            Return IsHumble(i \ 2)
        End If
        If i Mod 3 = 0 Then
            Return IsHumble(i \ 3)
        End If
        If i Mod 5 = 0 Then
            Return IsHumble(i \ 5)
        End If
        If i Mod 7 = 0 Then
            Return IsHumble(i \ 7)
        End If
        Return False
    End Function

    Sub Main()
        Dim LIMIT = Short.MaxValue
        Dim humble As New Dictionary(Of Integer, Integer)
        Dim count = 0L
        Dim num = 1L

        While count < LIMIT
            If (IsHumble(num)) Then
                Dim str = num.ToString
                Dim len = str.Length
                If len > 10 Then
                    Exit While
                End If
                If humble.ContainsKey(len) Then
                    humble(len) += 1
                Else
                    humble(len) = 1
                End If
                If count < 50 Then
                    Console.Write("{0} ", num)
                End If
                count += 1
            End If
            num += 1
        End While
        Console.WriteLine(vbNewLine)

        Console.WriteLine("Of the first {0} humble numbers:", count)
        num = 1
        While num < humble.Count
            If humble.ContainsKey(num) Then
                Dim c = humble(num)
                Console.WriteLine("{0,5} have {1,2} digits", c, num)
                num += 1
            Else
                Exit While
            End If
        End While
    End Sub

End Module


grammar CollectWords {
    token TOP {
        [^^ <word> $$ \n?]+
    }

    token word {
        [ <with_c> | <no_c> | \N ]+
    }

    token with_c {
        c <ie_part>
    }

    token no_c {
        <ie_part>
    }

    token ie_part {
        ie | ei | eie # a couple words in the list have "eie"
    }
}

class CollectWords::Actions {
    method TOP($/) {
        make $<word>».ast.flat.Bag;
    }

    method word($/) {
        if $<with_c> + $<no_c> {
            make flat $<with_c>».ast, $<no_c>».ast;
        } else {
            make ();
        }
    }

    method with_c($/) {
        make "c" X~ $<ie_part>.ast;
    }

    method no_c($/) {
        make "!c" X~ $<ie_part>.ast;
    }

    method ie_part($/) {
        if ~$/ eq 'eie' {
            make ('ei', 'ie');
        } else {
            make ~$/;
        }
    }
}

sub plausible($good, $bad, $msg) {
    if $good > 2*$bad {
        say "$msg: PLAUSIBLE ($good  vs. $bad ✘)";
        return True;
    } else {
        say "$msg: NOT PLAUSIBLE ($good  vs. $bad ✘)";
        return False;
    }
}

my $results = CollectWords.parsefile("unixdict.txt", :actions(CollectWords::Actions)).ast;

my $phrasetest = [&] plausible($results<!cie>, $results<!cei>, "I before E when not preceded by C"),
                     plausible($results<cei>, $results<cie>, "E before I when preceded by C");

say "I before E except after C: ", $phrasetest ?? "PLAUSIBLE" !! "NOT PLAUSIBLE";


import "/fmt" for Fmt
import "/math" for Int, Nums
import "/sort" for Find

var humble = Fn.new { |n|
    var h = List.filled(n, 0)
    h[0] = 1
    var next2 = 2
    var next3 = 3
    var next5 = 5
    var next7 = 7
    var i = 0
    var j = 0
    var k = 0
    var l = 0
    for (m in 1...n) {
        h[m] = Nums.min([next2, next3, next5, next7])
        if (h[m] == next2) {
            i = i + 1
            next2 = 2 * h[i]
        }
        if (h[m] == next3) {
            j = j + 1
            next3 = 3 * h[j]
        }
        if (h[m] == next5) {
            k = k + 1
            next5 = 5 * h[k]
        }
        if (h[m] == next7) {
            l = l + 1
            next7 = 7 * h[l]
        }
    }
    return h
}

var n = 43000 // say
var h = humble.call(n)
System.print("The first 50 humble numbers are:")
System.print(h[0..49])

var f = Find.all(h, Int.maxSafe) // binary search
var maxUsed = f[0] ? f[2].min + 1 : f[2].min
var maxDigits = 16 // Int.maxSafe (2^53 -1) has 16 digits
var counts = List.filled(maxDigits + 1, 0)
var digits = 1
var pow10 = 10
for (i in 0...maxUsed) {
    while (true) {
        if (h[i] >= pow10) {
            pow10 = pow10 * 10
            digits = digits + 1
        } else break
    }
    counts[digits] = counts[digits] + 1
}
System.print("\nOf the first %(Fmt.dc(0, maxUsed)) humble numbers:")
for (i in 1..maxDigits) {
    var s = (i != 1) ? "s" : ""
    System.print("%(Fmt.dc(9, counts[i])) have %(Fmt.d(2, i)) digit%(s)")
}


Red ["i before e except after c"]

testlist: function [wordlist /wfreq] [
	cie: cei: ie: ei: 0
	if not wfreq [forall wordlist [insert wordlist: next wordlist 1]]
	foreach [word freq] wordlist [
		parse word [ some [
			"cie" (cie: cie + freq)	|
			"cei" (cei: cei + freq)	|
			"ie"  (ie: ie + freq)	|
			"ei"  (ei: ei + freq)	|
			skip
		]]
	]
	print rejoin [
	"i is before e " ie " times, and also " cie " times following c.^/"
	"i is after e " ei " times, and also " cei " times following c.^/"
	"Hence ^"i before e^" is " either a: 2 * ei < ie [""] ["not "] "plausible,^/"
	"while ^"except after c^" is " either b: 2 * cie < cei [""] ["not "] "plausible.^/"
	"Overall the rule is " either a and b [""] ["not "] "plausible."]
]

print "Results for unixdict.txt:"
testlist read/lines http://wiki.puzzlers.org/pub/wordlists/unixdict.txt

print "^/Results for British National Corpus:"
bnc: next read/lines %1_2_all_freq.txt
spaces: charset "^- "
bnclist: collect [ foreach w bnc [
	if 3 = length? seq: split trim w spaces [
		keep seq/1 keep to-integer seq/3
]]]
testlist/wfreq bnclist


/*REXX program shows  plausibility  of  "I before E"  when not preceded by C,  and      */
/*───────────────────────────────────── "E before I"  when     preceded by C.           */
parse arg iFID .                                 /*obtain optional argument from the CL.*/
if iFID=='' | iFID=="," then iFID='UNIXDICT.TXT' /*Not specified?  Then use the default.*/
#.=0                                             /*zero out the various word counters.  */
     do r=0  while  lines(iFID)\==0              /*keep reading the dictionary 'til done*/
     u=space( lineIn(iFID), 0);      upper u     /*elide superfluous blanks and tabs.   */
     if u==''  then iterate                      /*Is it a blank line?   Then ignore it.*/
     #.words=#.words + 1                         /*keep running count of number of words*/
     if pos('EI', u)\==0 & pos('IE', u)\==0  then #.both=#.both + 1  /*the word has both*/
     call find  'ie'                                                 /*look for   ie    */
     call find  'ei'                                                 /*  "   "    ei    */
     end   /*r*/                                 /*at exit of DO loop,   R = # of lines.*/

L=length(#.words)                                /*use this to align the output numbers.*/
say 'lines in the  '         iFID         " dictionary: "            r
say 'words in the  '         iFID         " dictionary: "            #.words
say
say 'words with "IE" and "EI" (in same word): '    right(#.both, L)
say 'words with "IE" and     preceded by "C": '    right(#.ie.c ,L)
say 'words with "IE" and not preceded by "C": '    right(#.ie.z ,L)
say 'words with "EI" and     preceded by "C": '    right(#.ei.c ,L)
say 'words with "EI" and not preceded by "C": '    right(#.ei.z ,L)
say;                         mantra= 'The spelling mantra  '
p1=#.ie.z / max(1, #.ei.z);  phrase= '"I before E when not preceded by C"'
say mantra phrase   ' is '   word("im", 1 + (p1>2) )'plausible.'
p2=#.ie.c / max(1, #.ei.c);  phrase= '"E before I when     preceded by C"'
say mantra phrase   ' is '   word("im", 1 + (p2>2) )'plausible.'
po=(p1>2 & p2>2);            say 'Overall, it is'    word("im", 1 + po)'plausible.'
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
find: arg x;  s=1;  do forever;           _=pos(x, u, s);          if _==0  then return
                    if substr(u, _ - 1 + (_==1)*999, 1)=='C'  then #.x.c=#.x.c + 1
                                                              else #.x.z=#.x.z + 1
                    s=_ + 1                      /*handle the cases of multiple finds.  */
                    end   /*forever*/


var [const] BI=Import("zklBigNum");  // libGMP
var one   = BI(1), two   = BI(2), three = BI(3),
    five  = BI(5), seven = BI(7);

fcn humble(n){	// --> List of BigInt Humble numbers
   h:=List.createLong(n);  h.append(one);
   next2,next3 := two.copy(),  three.copy();
   next5,next7 := five.copy(), seven.copy();
   reg i=0,j=0,k=0,l=0;
   do(n-1){
      h.append( hm:=BI(next2.min(next3.min(next5.min(next7)))) );
      if(hm==next2) next2.set(two)  .mul(h[i+=1]);
      if(hm==next3) next3.set(three).mul(h[j+=1]);
      if(hm==next5) next5.set(five) .mul(h[k+=1]);
      if(hm==next7) next7.set(seven).mul(h[l+=1]);
   }
   h
}


# Project : I before E except after C

fn1 = "unixdict.txt"

fp = fopen(fn1,"r")
str = fread(fp, getFileSize(fp))
fclose(fp)
strcount = str2list(str)
see "The number of words in unixdict : " + len(strcount) + nl
cei = count(str, "cei")
cie = count(str, "cie")
ei = count(str, "ei")
ie = count(str, "ie")
see "Instances of cei : " + cei + nl
see "Instances of cie : " + cie + nl
see "Rule: 'e' before 'i' when preceded by 'c' is = "
if cei>cie see "plausible" + nl else see"not plausible" + nl ok
see "Instances of *ei, where * is not c : " + (ei-cei) + nl
see "Instances of *ie, where * is not c: " + (ie-cie) + nl
see "Rule: 'i' before 'e' when not preceded by 'c' is = "
if ie>ei see "plausible" + nl else see "not plausible" + nl ok
see "Overall the rule is : "
if cei>cie and ie>ei see "PLAUSIBLE" + nl else see "NOT PLAUSIBLE" + nl ok

func getFileSize fp
       c_filestart = 0
       c_fileend = 2
       fseek(fp,0,c_fileend)
       nfilesize = ftell(fp)
       fseek(fp,0,c_filestart)
       return nfilesize

func count(cString,dString)
       sum = 0
       while substr(cString,dString) > 0
               sum = sum + 1
               cString = substr(cString,substr(cString,dString)+len(string(sum)))
       end
       return sum


require 'open-uri'

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

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

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

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


use std::default::Default;
use std::ops::AddAssign;

use itertools::Itertools;
use reqwest::get;

#[derive(Default, Debug)]
struct Feature<T> {
    pub cie: T,
    pub xie: T,
    pub cei: T,
    pub xei: T,
}

impl AddAssign<Feature<bool>> for Feature<u64> {
    fn add_assign(&mut self, rhs: Feature<bool>) {
        self.cei += rhs.cei as u64;
        self.xei += rhs.xei as u64;
        self.cie += rhs.cie as u64;
        self.xie += rhs.xie as u64;
    }
}

fn check_feature(word: &str) -> Feature<bool> {
    let mut feature: Feature<bool> = Default::default();

    for window in word.chars().tuple_windows::<(char, char, char)>() {
        match window {
            ('c', 'e', 'i') => { feature.cei = true }
            ('c', 'i', 'e') => { feature.cie = true }
            (not_c, 'e', 'i') if not_c != 'c' => (feature.xei = true),
            (not_c, 'i', 'e') if not_c != 'c' => (feature.xie = true),
            _ => {}
        }
    }

    feature
}

fn maybe_is_feature_plausible(feature_count: u64, opposing_count: u64) -> Option<bool> {
    if feature_count > 2 * opposing_count { Some(true) } else if opposing_count > 2 * feature_count { Some(false) } else { None }
}

fn print_feature_plausibility(feature_plausibility: Option<bool>, feature_name: &str) {
    let plausible_msg =
        match feature_plausibility {
            None => " is implausible",
            Some(true) => "is plausible",
            Some(false) => "is definitely implausible",
        };

    println!("{} {}", feature_name, plausible_msg)
}

fn main() {
    let mut res = get(" http://wiki.puzzlers.org/pub/wordlists/unixdict.txt").unwrap();
    let texts = res.text().unwrap();

    let mut feature_count: Feature<u64> = Default::default();
    for word in texts.lines() {
        let feature = check_feature(word);
        feature_count += feature;
    }

    println!("Counting {:#?}", feature_count);

    let xie_plausibility =
        maybe_is_feature_plausible(feature_count.xie, feature_count.cie);
    let cei_plausibility =
        maybe_is_feature_plausible(feature_count.cei, feature_count.xei);

    print_feature_plausibility(xie_plausibility, "I before E when not preceded by C");
    print_feature_plausibility(cei_plausibility, "E before I when preceded by C");
    println!("The rule in general is {}",
             if xie_plausibility.unwrap_or(false) && cei_plausibility.unwrap_or(false)
             { "Plausible" } else { "Implausible" }
    );
}


object I_before_E_except_after_C extends App {
  val testIE1 = "(^|[^c])ie".r // i before e when not preceded by c
  val testIE2 = "cie".r // i before e when preceded by c
  var countsIE = (0,0)

  val testCEI1 = "cei".r // e before i when preceded by c
  val testCEI2 = "(^|[^c])ei".r // e before i when not preceded by c
  var countsCEI = (0,0)

  scala.io.Source.fromURL("http://wiki.puzzlers.org/pub/wordlists/unixdict.txt").getLines.map(_.toLowerCase).foreach{word =>
    if (testIE1.findFirstIn(word).isDefined) countsIE = (countsIE._1 + 1, countsIE._2)
    if (testIE2.findFirstIn(word).isDefined) countsIE = (countsIE._1, countsIE._2 + 1)
    if (testCEI1.findFirstIn(word).isDefined) countsCEI = (countsCEI._1 + 1, countsCEI._2)
    if (testCEI2.findFirstIn(word).isDefined) countsCEI = (countsCEI._1, countsCEI._2 + 1)
  }

  def plausible(counts: (Int,Int)) = counts._1 > (2 * counts._2)
  def plausibility(plausible: Boolean) = if (plausible) "plausible" else "implausible"
  def plausibility(counts: (Int, Int)): String = plausibility(plausible(counts))
  println("I before E when not preceded by C: "+plausibility(countsIE))
  println("E before I when preceded by C: "+plausibility(countsCEI))
  println("Overall: "+plausibility(plausible(countsIE) && plausible(countsCEI)))
}


$ include "seed7_05.s7i";
  include "gethttp.s7i";
  include "float.s7i";

const integer: PLAUSIBILITY_RATIO is 2;

const func boolean: plausibilityCheck (in string: comment, in integer: x, in integer: y) is func
  result
    var boolean: plausible is FALSE;
  begin
    writeln("  Checking plausibility of: " <& comment);
    if x > PLAUSIBILITY_RATIO * y then
      writeln("    PLAUSIBLE. As we have counts of " <& x <& " vs " <& y <&
              " words, a ratio of " <& flt(x) / flt(y) digits 1 lpad 4 <& " times");
    elsif x > y then
      writeln("    IMPLAUSIBLE. As although we have counts of " <& x <& " vs " <& y <&
              " words, a ratio of " <& flt(x) / flt(y) digits 1 lpad 4 <& " times does not make it plausible");
    else
      writeln("    IMPLAUSIBLE, probably contra-indicated. As we have counts of " <& x <& " vs " <& y <&
              " words, a ratio of " <& flt(x) / flt(y) digits 1 lpad 4 <& " times");
    end if;
    plausible := x > PLAUSIBILITY_RATIO * y;
  end func;

const func integer: count (in string: stri, in array string: words) is func
  result
    var integer: count is 0;
  local
    var integer: index is 0;
  begin
    for key index range words do
      if pos(words[index], stri) <> 0 then
        incr(count);
      end if;
    end for;
  end func;

const proc: main is func
  local
    var array string: words is 0 times "";
    var integer: cie is 0;
    var integer: cei is 0;
    var integer: not_c_ie is 0;
    var integer: not_c_ei is 0;
  begin
    words := split(lower(getHttp("wiki.puzzlers.org/pub/wordlists/unixdict.txt")), "\n");
    cie := count("cie", words);
    cei := count("cei", words);
    not_c_ie := count("ie", words) - cie;
    not_c_ei := count("ei", words) - cei;
    writeln("Checking plausibility of \"I before E except after C\":");
    if plausibilityCheck("I before E when not preceded by C", not_c_ie, not_c_ei) and
        plausibilityCheck("E before I when preceded by C", cei, cie) then
      writeln("OVERALL IT IS PLAUSIBLE!");
    else
      writeln("OVERALL IT IS IMPLAUSIBLE!");
      writeln("(To be plausible, one word count must exceed another by " <& PLAUSIBILITY_RATIO <& " times)");
    end if;
  end func;


import Foundation

let request = NSURLRequest(URL: NSURL(string: "http://wiki.puzzlers.org/pub/wordlists/unixdict.txt")!)

NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue()) {res, data, err in
    if (data != nil) {
        if let fileAsString = NSString(data: data, encoding: NSUTF8StringEncoding) {
            var firstCase = false
            var secondCase = false
            var cie = 0
            var cei = 0
            var not_c_ie = 0
            var not_c_ei = 0
            let words = fileAsString.componentsSeparatedByString("\n")
            for word in words {
                var wordRegex = RegexMutable(word as String)
                if (wordRegex["cie"]) {
                    cie++
                }
                if (wordRegex["cei"]) {
                    cei++
                }
                if (wordRegex["(^ie|[^c]ie)"].matches().count != 0) {
                    not_c_ie++
                }
                if (wordRegex["(^ei|[^c]ei)"].matches().count != 0) {
                    not_c_ei++
                }
            }

            if (not_c_ie > not_c_ei * 2) {
                println("I before E when not preceded by C is plausable")
                firstCase = true
            } else {
                println("I before E when not preceded by C is not plausable")
            }

            if (cei > cie * 2) {
                secondCase = true
                println("E before I when preceded by C is plausable")
            } else {
                println("E before I when preceded by C is not plausable")
            }

            if (firstCase && secondCase) {
                println("I before E except after C is plausible")
            } else {
                println("I before E except after C is not plausible")
            }
        }
    }
}

CFRunLoopRun()


DEF EOF(f)
    IF END #f THEN LET EOF = -1 ELSE LET EOF = 0
END DEF

CLEAR
OPEN #1: NAME "UNIXDICT.TXT", org text, ACCESS INPUT, create old
DO
   LINE INPUT #1: w$
   IF POS(w$,"ie")<>0 THEN
      IF POS(w$,"cie")<>0 THEN LET ci = ci+1 ELSE LET xi = xi+1
   END IF
   IF POS(w$,"ei")<>0 THEN
      IF POS(w$,"cei")<>0 THEN LET ce = ce+1 ELSE LET xe = xe+1
   END IF
LOOP WHILE (NOT EOF(1)<>0)
CLOSE #1

PRINT "CIE:"; ci
PRINT "xIE:"; xi
PRINT "CEI:"; ce
PRINT "xEI:"; xe
PRINT
PRINT "I before E when not preceded by C: ";
IF 2*xi <= ci THEN PRINT "not ";
PRINT "plausible."
PRINT "E before I when preceded by C: ";
IF 2*ce <= xe THEN PRINT "not ";
PRINT "plausible."
END


package require http

variable PLAUSIBILITY_RATIO 2.0
proc plausible {description x y} {
    variable PLAUSIBILITY_RATIO
    puts "  Checking plausibility of: $description"
    if {$x > $PLAUSIBILITY_RATIO * $y} {
	set conclusion "PLAUSIBLE"
	set fmt "As we have counts of %i vs %i words, a ratio of %.1f times"
	set result true
    } elseif {$x > $y} {
	set conclusion "IMPLAUSIBLE"
	set fmt "As although we have counts of %i vs %i words,"
	append fmt " a ratio of %.1f times does not make it plausible"
	set result false
    } else {
	set conclusion "IMPLAUSIBLE, probably contra-indicated"
	set fmt "As we have counts of %i vs %i words, a ratio of %.1f times"
	set result false
    }
    puts [format "    %s.\n    $fmt" $conclusion $x $y [expr {double($x)/$y}]]
    return $result
}

set t [http::geturl http://wiki.puzzlers.org/pub/wordlists/unixdict.txt]
set words [split [http::data $t] "\n"]
http::cleanup $t
foreach {name pattern} {ie (?:^|[^c])ie ei (?:^|[^c])ei cie cie cei cei} {
    set count($name) [llength [lsearch -nocase -all -regexp $words $pattern]]
}

puts "Checking plausibility of \"I before E except after C\":"
if {
    [plausible "I before E when not preceded by C" $count(ie) $count(ei)] &&
    [plausible "E before I when preceded by C" $count(cei) $count(cie)]
} then {
    puts "\nOVERALL IT IS PLAUSIBLE!"
} else {
    puts "\nOVERALL IT IS IMPLAUSIBLE!"
}
puts "\n(To be plausible, one word count must exceed another by\
	$PLAUSIBILITY_RATIO times)"


$$ MODE TUSCRIPT,{}
words=REQUEST("http://wiki.puzzlers.org/pub/wordlists/unixdict.txt")
size=SIZE(words)
ieei=cie=xie=cei=xei=0

LOOP word=words
IF (word.nc." ie "," ei ") CYCLE

IF (word.ct." ie "&& word.ct." ei ") THEN
 ieei=ieei+1
  IF (word.ct." Cie ") THEN
   cie=cie+1
  ELSEIF (word.ct." Cei ") THEN
   cei=cei+1
  ELSE
   xei=xei+1
  ENDIF
ENDIF

IF (word.ct." ie ") THEN
  IF (word.ct." Cie ") THEN
    cie=cie+1
  ELSE
    xie=xie+1
  ENDIF
ELSEIF (word.ct." ei ") THEN
  IF (word.ct." Cei ") THEN
    cei=cei+1
  ELSE
    xei=xei+1
  ENDIF
ENDIF

ENDLOOP

PRINT "ieee ", ieei
PRINT "cie  ", cie
PRINT "xie  ", xie
PRINT "cei  ", cei
PRINT "xei  ", xei

doublexei=2*xei
doublecei=cei*2

IF (xie>doublexei) THEN
 check1="plausible"
ELSE
 check1="not plausible"
ENDIF

IF (cei>xei) THEN
 check2="plausible"
ELSE
 check2="not plausible"
ENDIF
IF (check1==check2) THEN
 checkall="plausible"
ELSE
 checkall="not plausible"
ENDIF

TRAcE *check1,check2,checkall


#!/bin/sh

matched() {
  grep -Poe "$1" unixdict.txt | wc -l
}

check() {
  local num_for="$(matched "$3")"
  local num_against="$(matched "$2")"
  if [ "$num_for" -le "$(expr 2 \* "$num_against")" ]; then
    echo "Clause $1 not plausible ($num_for examples; $num_against counterexamples)"
    return 1
  else
    echo "Clause $1 is plausible ($num_for examples; $num_against counterexamples)"
    return 0
  fi
}

check 1 '(?<!c)ei' '(?<!c)ie'
PLAUSIBLE_1=$?
check 2 'cie' 'cei'
PLAUSIBLE_2=$?
if [ $PLAUSIBLE_1 -eq 0 -a $PLAUSIBLE_2 -eq 0 ]; then
  echo "Overall, the rule is plausible"
else
  echo "Overall, the rule is not plausible"
fi


Set objFSO = CreateObject("Scripting.FileSystemObject")
Set srcFile = objFSO.OpenTextFile(objFSO.GetParentFolderName(WScript.ScriptFullName) &_
	"\unixdict.txt",1,False,0)

cei = 0 : cie = 0 : ei = 0 : ie = 0

Do Until srcFile.AtEndOfStream
	word = srcFile.ReadLine
	If InStr(word,"cei") Then
		cei = cei + 1
	ElseIf InStr(word,"cie") Then
		cie = cie + 1
	ElseIf InStr(word,"ei") Then
		ei = ei + 1
	ElseIf InStr(word,"ie") Then
		ie = ie + 1
	End If
Loop

FirstClause = False
SecondClause = False
Overall = False

'testing the first clause
If  ie > ei*2 Then
	WScript.StdOut.WriteLine "I before E when not preceded by C is plausible."
	FirstClause = True
Else
	WScript.StdOut.WriteLine "I before E when not preceded by C is NOT plausible."
End If

'testing the second clause
If cei > cie*2 Then
	WScript.StdOut.WriteLine "E before I when not preceded by C is plausible."
	SecondClause = True
Else
	WScript.StdOut.WriteLine "E before I when not preceded by C is NOT plausible."
End If

'overall clause
If FirstClause And SecondClause Then
	WScript.StdOut.WriteLine "Overall it is plausible."
Else
	WScript.StdOut.WriteLine "Overall it is NOT plausible."
End If

srcFile.Close
Set objFSO = Nothing


Option Compare Binary
Option Explicit On
Option Infer On
Option Strict On

Imports System.Text.RegularExpressions

#Const USE_REGEX = False

Module Program
    ' Supports both local and remote files
    Const WORDLIST_URI = "http://wiki.puzzlers.org/pub/wordlists/unixdict.txt"

    ' The support factor of a word for EI or IE is the number of occurrences that support the rule minus the number that oppose it.
    ' I.e., for IE:
    '   - increased when not preceded by C
    '   - decreased when preceded by C
    ' and for EI:
    '   - increased when preceded by C
    '   - decreased when not preceded by C
    Private Function GetSupportFactor(word As String) As (IE As Integer, EI As Integer)
        Dim IE, EI As Integer

        ' Enumerate the letter pairs in the word.
        For i = 0 To word.Length - 2
            Dim pair = word.Substring(i, 2)

            ' Instances at the beginning of a word count towards the factor and are treated as not preceded by C.
            Dim prevIsC As Boolean = i > 0 AndAlso String.Equals(word(i - 1), "c"c, StringComparison.OrdinalIgnoreCase)

            If pair.Equals("ie", StringComparison.OrdinalIgnoreCase) Then
                IE += If(Not prevIsC, 1, -1)
            ElseIf pair.Equals("ei", StringComparison.OrdinalIgnoreCase) Then
                EI += If(prevIsC, 1, -1)
            End If
        Next

        If Math.Abs(IE) > 1 Or Math.Abs(EI) > 1 Then Debug.WriteLine($"{word}: {GetSupportFactor}")
        Return (IE, EI)
    End Function

    ' Returns the number of words that support or oppose the rule.
    Private Function GetPlausabilities(words As IEnumerable(Of String)) As (ieSuppCount As Integer, ieOppCount As Integer, eiSuppCount As Integer, eiOppCount As Integer)
        Dim ieSuppCount, ieOppCount, eiSuppCount, eiOppCount As Integer

        For Each word In words
            Dim status = GetSupportFactor(word)
            If status.IE > 0 Then
                ieSuppCount += 1
            ElseIf status.IE < 0 Then
                ieOppCount += 1
            End If
            If status.EI > 0 Then
                eiSuppCount += 1
            ElseIf status.EI < 0 Then
                eiOppCount += 1
            End If
        Next

        Return (ieSuppCount, ieOppCount, eiSuppCount, eiOppCount)
    End Function

    ' Takes entire file instead of individual words.
    ' Returns the number of instances of IE or EI that support or oppose the rule.
    Private Function GetPlausabilitiesRegex(words As String) As (ieSuppCount As Integer, ieOppCount As Integer, eiSuppCount As Integer, eiOppCount As Integer)
        ' Gets number of occurrences of the pattern, case-insensitive.
        Dim count = Function(pattern As String) Regex.Matches(words, pattern, RegexOptions.IgnoreCase).Count

        Dim ie = count("[^c]ie")
        Dim ei = count("[^c]ei")
        Dim cie = count("cie")
        Dim cei = count("cei")

        Return (ie, cie, cei, ei)
    End Function

    Sub Main()
        Dim file As String
        Dim wc As New Net.WebClient()
        Try
            Console.WriteLine("Fetching file...")
            file = wc.DownloadString(WORDLIST_URI)
            Console.WriteLine("Success.")
            Console.WriteLine()
        Catch ex As Net.WebException
            Console.WriteLine(ex.Message)
            Exit Sub
        Finally
            wc.Dispose()
        End Try

#If USE_REGEX Then
        Dim res = GetPlausabilitiesRegex(file)
#Else
        Dim words = file.Split({vbCr, vbLf}, StringSplitOptions.RemoveEmptyEntries)
        Dim res = GetPlausabilities(words)
#End If

        Dim PrintResult =
        Function(suppCount As Integer, oppCount As Integer, printEI As Boolean) As Boolean
            Dim ratio = suppCount / oppCount,
                plausible = ratio > 2
#If Not USE_REGEX Then
            Console.WriteLine($"    Words with no instances of {If(printEI, "EI", "IE")} or equal numbers of supporting/opposing occurrences: {words.Length - suppCount - oppCount}")
#End If
            Console.WriteLine($"    Number supporting: {suppCount}")
            Console.WriteLine($"    Number opposing: {oppCount}")
            Console.WriteLine($"    {suppCount}/{oppCount}={ratio:N3}")
            Console.WriteLine($"    Rule therefore IS {If(plausible, "", "NOT ")}plausible.")
            Return plausible
        End Function

#If USE_REGEX Then
        Console.WriteLine($"Total occurrences of IE: {res.ieOppCount + res.ieSuppCount}")
        Console.WriteLine($"Total occurrences of EI: {res.eiOppCount + res.eiSuppCount}")
#Else
        Console.WriteLine($"Total words: {words.Length}")
#End If

        Console.WriteLine()
        Console.WriteLine("""IE is not preceded by C""")
        Dim iePlausible = PrintResult(res.ieSuppCount, res.ieOppCount, False)

        Console.WriteLine()
        Console.WriteLine("""EI is preceded by C""")
        Dim eiPlausible = PrintResult(res.eiSuppCount, res.eiOppCount, True)

        Console.WriteLine()
        Console.WriteLine($"Rule thus overall IS {If(iePlausible AndAlso eiPlausible, "", "NOT ")}plausible.")
    End Sub
End Module