Function validate_iban(s)
	validate_iban = Chr(34) & s & Chr(34) & " is NOT valid."
	Set cn_len = CreateObject("Scripting.Dictionary")
	With cn_len
		.Add "AL",28 : .Add "AD",24 : .Add "AT",20 : .Add "AZ",28 : .Add "BH",22 : .Add "BE",16
		.Add "BA",20 : .Add "BR",29 : .Add "BG",22 : .Add "CR",21 : .Add "HR",21 : .Add "CY",28
		.Add "CZ",24 : .Add "DK",18 : .Add "DO",28 : .Add "EE",20 : .Add "FO",18 : .Add "FI",18
		.Add "FR",27 : .Add "GE",22 : .Add "DE",22 : .Add "GI",23 : .Add "GR",27 : .Add "GL",18
		.Add "GT",28 : .Add "HU",28 : .Add "IS",26 : .Add "IE",22 : .Add "IL",23 : .Add "IT",27
		.Add "JO",30 : .Add "KZ",20 : .Add "KW",30 : .Add "LV",21 : .Add "LB",28 : .Add "LI",21
		.Add "LT",20 : .Add "LU",20 : .Add "MK",19 : .Add "MT",31 : .Add "MR",27 : .Add "MU",30
		.Add "MC",27 : .Add "MD",24 : .Add "ME",22 : .Add "NL",18 : .Add "NO",15 : .Add "PK",24
		.Add "PS",29 : .Add "PL",28 : .Add "PT",25 : .Add "QA",29 : .Add "RO",24 : .Add "SM",27
		.Add "SA",24 : .Add "RS",22 : .Add "SK",24 : .Add "SI",19 : .Add "ES",24 : .Add "SE",24
		.Add "CH",21 : .Add "TN",24 : .Add "TR",26 : .Add "AE",23 : .Add "GB",22 : .Add "VG",24
	End With
	iban = Replace(s," ","")
	If cn_len.Exists(Left(iban,2)) And Len(iban) = cn_len.Item(Left(iban,2)) Then
		'move the first 4 characters to the end
		iban = Mid(iban,5,Len(iban)-4) & Left(iban,4)
		'convert letters to numbers A=10 to Z=35
		D = ""
		For i = 1 To Len(iban)
			If Asc(Mid(iban,i,1)) >= 65 And Asc(Mid(iban,i,1)) <= 90 Then
				D = D & CStr(Asc(Mid(iban,i,1)) - 55)
			Else
				D = D & Mid(iban,i,1)
			End If
		Next
		'piece-wise modulo calculation
		Do
			If Len(D) > 9 Then
				N = CLng(Left(D,9)) Mod 97
				D = CStr(N) & Mid(D,10,Len(D)-9)
			Else
				N = CLng(Left(D,9)) Mod 97
				Exit Do
			End If
		Loop
		If N = 1 Then
			validate_iban = Chr(34) & s & Chr(34) & " is valid."
		End If
	End If
End Function

'test several scenarios
WScript.StdOut.WriteLine validate_iban("GB82 WEST 1234 5698 7654 32")
WScript.StdOut.WriteLine validate_iban("GB82WEST12345698765432")
WScript.StdOut.WriteLine validate_iban("gb82 west 1234 5698 7654 32")
WScript.StdOut.WriteLine validate_iban("GB82 TEST 1234 5698 7654 32")
WScript.StdOut.WriteLine validate_iban("GR16 0110 1250 0000 0001 2300 695")
WScript.StdOut.WriteLine validate_iban("GB29 NWBK 6016 1331 9268 19")
WScript.StdOut.WriteLine validate_iban("SA03 8000 0000 6080 1016 7519")
WScript.StdOut.WriteLine validate_iban("CH93 0076 2011 6238 5295 7")
WScript.StdOut.WriteLine validate_iban("IL62 0108 0000 0009 9999 999")
WScript.StdOut.WriteLine validate_iban("IL62-0108-0000-0009-9999-999")
WScript.StdOut.WriteLine validate_iban("US12 3456 7890 0987 6543 210")
WScript.StdOut.WriteLine validate_iban("GR16 0110 1250 0000 0001 2300 695X")


#include <iostream>
#include <fstream>
#include <string>
#include <tuple>
#include <vector>
#include <stdexcept>
#include <boost/regex.hpp>

struct Claim {
        Claim(const std::string& name) : name_(name), pro_(0), against_(0), propats_(), againstpats_() {
        }

        void add_pro(const std::string& pat) {
               propats_.push_back(std::make_tuple(boost::regex(pat), pat[0] == '^'));
        }
        void add_against(const std::string& pat) {
               againstpats_.push_back(std::make_tuple(boost::regex(pat), pat[0] == '^'));
        }
        bool plausible() const { return pro_ > against_*2; }
        void check(const char * buf, uint32_t len) {
                for (auto i = propats_.begin(), ii = propats_.end(); i != ii; ++i) {
                        uint32_t pos = 0;
                        boost::cmatch m;
                        if (std::get<1>(*i) && pos > 0) continue;
                        while (pos < len && boost::regex_search(buf+pos, buf+len, m, std::get<0>(*i))) {
                                ++pro_;
                                if (pos > 0) std::cerr << name_ << " [pro] multiple matches in: " << buf << "\n";
                                pos += m.position() + m.length();
                        }
                }
                for (auto i = againstpats_.begin(), ii = againstpats_.end(); i != ii; ++i) {
                        uint32_t pos = 0;
                        boost::cmatch m;
                        if (std::get<1>(*i) && pos > 0) continue;
                        while (pos < len && boost::regex_search(buf+pos, buf+len, m, std::get<0>(*i))) {
                                ++against_;
                                if (pos > 0) std::cerr << name_ << " [against] multiple matches in: " << buf << "\n";
                                pos += m.position() + m.length();
                        }
                }
        }
        friend std::ostream& operator<<(std::ostream& os, const Claim& c);
private:
        std::string name_;
        uint32_t pro_;
        uint32_t against_;
        // tuple<regex,begin only>
        std::vector<std::tuple<boost::regex,bool>> propats_;
        std::vector<std::tuple<boost::regex,bool>> againstpats_;
};

std::ostream& operator<<(std::ostream& os, const Claim& c) {
        os << c.name_ << ": matches: " << c.pro_ << " vs. counter matches: " << c.against_ << ". ";
        os << "Plausibility: " << (c.plausible() ? "yes" : "no") << ".";
        return os;
}

int main(int argc, char ** argv) {
        try {
                if (argc < 2) throw std::runtime_error("No input file.");
                std::ifstream is(argv[1]);
                if (! is) throw std::runtime_error("Input file not valid.");

                Claim ieclaim("[^c]ie");
                ieclaim.add_pro("[^c]ie");
                ieclaim.add_pro("^ie");
                ieclaim.add_against("[^c]ei");
                ieclaim.add_against("^ei");

                Claim ceiclaim("cei");
                ceiclaim.add_pro("cei");
                ceiclaim.add_against("cie");

                {
                        const uint32_t MAXLEN = 32;
                        char buf[MAXLEN];
                        uint32_t longest = 0;
                        while (is) {
                                is.getline(buf, sizeof(buf));
                                if (is.gcount() <= 0) break;
                                else if (is.gcount() > longest) longest = is.gcount();
                                ieclaim.check(buf, is.gcount());
                                ceiclaim.check(buf, is.gcount());
                        }
                        if (longest >= MAXLEN) throw std::runtime_error("Buffer too small.");
                }

                std::cout << ieclaim << "\n";
                std::cout << ceiclaim << "\n";
                std::cout << "Overall plausibility: " << (ieclaim.plausible() && ceiclaim.plausible() ? "yes" : "no") << "\n";

        } catch (const std::exception& ex) {
                std::cerr << "*** Error: " << ex.what() << "\n";
                return -1;
        }
        return 0;
}


using System;
using System.Collections.Generic;

namespace HumbleNumbers {
    class Program {
        static bool IsHumble(int i) {
            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;
        }

        static void Main() {
            var limit = short.MaxValue;
            Dictionary<int, int> humble = new Dictionary<int, int>();
            var count = 0;
            var num = 1;

            while (count < limit) {
                if (IsHumble(num)) {
                    var str = num.ToString();
                    var len = str.Length;
                    if (humble.ContainsKey(len)) {
                        humble[len]++;
                    } else {
                        humble[len] = 1;
                    }
                    if (count < 50) Console.Write("{0} ", num);
                    count++;
                }
                num++;
            }
            Console.WriteLine("\n");

            Console.WriteLine("Of the first {0} humble numbers:", count);
            num = 1;
            while (num < humble.Count - 1) {
                if (humble.ContainsKey(num)) {
                    var c = humble[num];
                    Console.WriteLine("{0,5} have {1,2} digits", c, num);
                    num++;
                } else {
                    break;
                }
            }
        }
    }
}


#lang racket

; Hunt the Wumpus

(require racket/random)

(struct game-state (labyrinth
                    player-location
                    number-of-arrows
                    wumpus-location
                    bat-locations
                    pit-locations) #:mutable #:transparent)

; The labyrinth-data list contains 20 lists that hold the information for
; each rooms connections to other rooms in the labyrinth.
; e.g. (1 2 5 8) shows that room 1 has connections to rooms 2, 5 and 8.

(define labyrinth-data '(
                         (1 2 5 8)
                         (2 1 3 10)
                         (3 2 4 12)
                         (4 3 5 14)
                         (5 1 4 6)
                         (6 5 7 15)
                         (7 6 8 17)
                         (8 1 7 9)
                         (9 8 10 18)
                         (10 2 9 11)
                         (11 10 12 19)
                         (12 3 11 13)
                         (13 12 14 20)
                         (14 4 13 15)
                         (15 6 14 16)
                         (16 15 17 20)
                         (17 7 16 18)
                         (18 9 17 19)
                         (19 11 18 20)
                         (20 13 16 19)))

(define example-game-state (game-state labyrinth-data
                                       1
                                       5
                                       2
                                       '(3 4)
                                       '(5 6)))

(define (new-game-state)
  (let ([ngs (game-state labyrinth-data 1 5 1 '(1 1) '(1 1))])
    (set-game-state-wumpus-location! ngs (safe-empty-room ngs))
    (set-game-state-bat-locations! ngs (list (safe-empty-room ngs)))
    (set-game-state-bat-locations! ngs (cons (safe-empty-room ngs)
                                             (game-state-bat-locations ngs)))
    (set-game-state-pit-locations! ngs (list (safe-empty-room ngs)))
    (set-game-state-pit-locations! ngs (cons (safe-empty-room ngs)
                                             (game-state-pit-locations ngs)))
    ngs))

(define (move-player room current-game-state)
  (set-game-state-player-location! current-game-state room))

(define (disturb-wumpus current-game-state)
  (if (<= (random) 0.75)
      (set-game-state-wumpus-location! current-game-state
                                       (room-for-wumpus-move current-game-state))
      #f))

(define (room-for-wumpus-move current-game-state)
  (let ([choices (append (neighbours
                          (game-state-wumpus-location current-game-state)
                          current-game-state)
                         (list (game-state-wumpus-location current-game-state)))])
    (findf (λ (room) (and (not (pit-room? room current-game-state))
                          (not (bat-room? room current-game-state)))) choices)))

(define (lost? current-game-state)
  (or (= (game-state-player-location current-game-state) (game-state-wumpus-location current-game-state))
      (member (game-state-player-location current-game-state)
              (game-state-pit-locations current-game-state))
      (= 0 (game-state-number-of-arrows current-game-state))))

(define (won? current-game-state)
  (= 0 (game-state-wumpus-location current-game-state)))

(define (shoot-arrow room current-game-state)
  (if (= room (game-state-wumpus-location current-game-state))
      (set-game-state-wumpus-location! current-game-state 0)
      (disturb-wumpus current-game-state))
  (set-game-state-number-of-arrows! current-game-state
                                    (- (game-state-number-of-arrows current-game-state) 1)))

(define (move-player-with-bats current-game-state)
  (set-game-state-player-location! current-game-state (safe-empty-room current-game-state)))

(define (safe-empty-room current-game-state)
  (let ([room (+ 1 (random 20))])
    (if (or (= room (game-state-wumpus-location current-game-state))
            (= room (game-state-player-location current-game-state))
            (member room (game-state-bat-locations current-game-state))
            (member room (game-state-pit-locations current-game-state)))
        (safe-empty-room current-game-state)
        room)))

(define (find-room room-number current-game-state)
  (assoc room-number (game-state-labyrinth current-game-state)))

(define (neighbours room-number current-game-state)
  (rest (find-room room-number current-game-state)))

(define (pit-room? room current-game-state)
  (member room (game-state-pit-locations current-game-state)))

(define (bat-room? room current-game-state)
  (member room (game-state-bat-locations current-game-state)))

(define (nearby? room-number entity-room-number current-game-state)
  (member entity-room-number (neighbours room-number current-game-state)))

(define (any-of-in? of-lst in-lst)
  (for/or ([item of-lst])
    (member item in-lst)))

(define (pit-nearby? room current-game-state)
  (any-of-in? (neighbours room current-game-state) (game-state-pit-locations current-game-state)))

(define (bat-nearby? room current-game-state)
  (any-of-in? (neighbours room current-game-state) (game-state-bat-locations current-game-state)))

(define (wumpus-nearby? room current-game-state)
  (member (game-state-wumpus-location current-game-state) (neighbours room current-game-state)))

(define (resolve-command str-list current-game-state)
  (let ([command (string-upcase (first str-list))]
        [room (string->number (second str-list))])
    (if (nearby? (game-state-player-location current-game-state)
                 room current-game-state)
        (cond [(equal? command "W") (if (bat-room? room current-game-state)
                                        (display-bat-attack current-game-state)
                                        (move-player room current-game-state))]
              [(equal? command "S") (shoot-arrow room current-game-state)]
              [else (displayln "Unknown command")])
        (displayln "You cannot move or shoot there!"))))

(define (display-bat-attack current-game-state)
  (move-player-with-bats current-game-state)
  (display "Argh! A Giant Bat has carried you to room ")
  (displayln (game-state-player-location current-game-state)))

(define (display-hazards current-game-state)
  (when (wumpus-nearby? (game-state-player-location current-game-state) current-game-state)
    (displayln "You smell something nearby."))
  (when (bat-nearby? (game-state-player-location current-game-state) current-game-state)
    (displayln "You hear a rustling."))
  (when (pit-nearby? (game-state-player-location current-game-state) current-game-state)
    (displayln "You feel a cold wind blowing from a nearby cavern.")))

(define (display-room-numbers lst)
  (display (string-join (map number->string lst) ", " #:before-last " or " #:after-last ".")))

(define (display-lost-message current-game-state)
  (cond [(= (game-state-player-location current-game-state)
            (game-state-wumpus-location current-game-state)) (displayln "The Wumpus has eaten you!")]
        [(member (game-state-player-location current-game-state)
                 (game-state-pit-locations current-game-state)) (displayln "You have fallen down a pit!")]
        [(= 0 (game-state-number-of-arrows current-game-state)) (displayln "You have run out of arrows.")]
        [else (displayln "Unknown loss")]))

(define (display-won-message current-game-state)
  (displayln "Congratulations, you have slain the Wumpus!"))

(define (display-information current-game-state)
  (display "You can (W)alk or (S)hoot to rooms ")
  (display-room-numbers (neighbours (game-state-player-location current-game-state) current-game-state))
  (newline)
  (display "You have ")
  (display (game-state-number-of-arrows current-game-state))
  (displayln " arrows left.")
  (display-hazards current-game-state))

(define (debug-game-state current-game-state)
  (display "    Player Location : ")
  (displayln (game-state-player-location current-game-state))
  (display "    Wumpus Location : ")
  (displayln (game-state-wumpus-location current-game-state))
  (display "    Bat Locations : ")
  (displayln (game-state-bat-locations current-game-state))
  (display "    Pit Locations : ")
  (displayln (game-state-pit-locations current-game-state)))

(define (game-loop current-game-state)
  ;(debug-game-state current-game-state)
  (display-information current-game-state)
  (resolve-command (string-split (read-line)) current-game-state)
  (cond [(lost? current-game-state) (display-lost-message current-game-state)]
        [(won? current-game-state) (display-won-message current-game-state)]
        [else (game-loop current-game-state)]))

(define (start-game)
  (let ([current-game-state (new-game-state)])
    (game-loop current-game-state)))


Red [
	Title:	 "Hunt the Wumpus"
	Author:  "Gregg Irwin"
	Version: 1.0.2
	Comment: {
		2001 Notes:
		I found an old version, in C (by Eric Raymond), which was adapted from
		an even older version, in BASIC (by Magnus Olsson), that had been found
		in a SIMTEL archive. It's got lineage.

		As of 22-Oct-2001, it appears to work, though I haven't traced the
		arrow path'ing logic yet nor made it smart. Arrows can go pretty much
		anywhere you tell them and, yes, you can shoot yourself as in the
		original.

		I tweaked a few strings, but the instructions are almost unscathed.

		Ahhh, it takes me back to my Dad's HP85 with the built-in 5 inch
		monochrome screen, tape drive, and thermal printer...

		2016 Notes: This was one of the very first programs I wrote in REBOL.
		I could update it, but we all have to start somewhere, and I think
		it has a certain charm. It is neither concise, nor idiomatic Redbol
		(a portmanteau of Red and Rebol), but making it so will be a good
		exercise for the reader, if they so choose. And if they don't, that's
		fine too, because you can write your Red code however you want.

		And for the kids out there, my Dad's HP85 was a beast. He paid a LOT
		of money to get the extra 16K RAM module. 32K RAM total. Believe it.
		Only 36 years ago.
	}
	history: {
		1.0.0 22-Mar-2001 {Initial Release}
		1.0.1 11-Apr-2002 {Fixed bug where the Wumpus might eat you after you shot him.}
		1.0.2 25-Jun-2016 {Ported to Red 0.6.1}
	}
]

arrow-count:  0

; indexes into location block
player: 1
wumpus: 2
pit-1:	3
pit-2:	4
bats-1: 5
bats-2: 6

start-loc: []
loc: []
winner: none
finished: false

; The cave is a dodecahedron. Each block is a room containing the
; number for the rooms it is connected to.
cave: [
	[2 5 8]    [1 3 10]  [2 4 12]	[3 5 14]   [1 4 6]
	[5 7 15]   [6 8 17]  [1 7 9]	[8 10 18]  [2 9 11]
	[10 12 19] [3 11 13] [12 14 20] [4 13 15]  [6 14 16]
	[15 17 20] [7 16 18] [9 17 19]	[11 18 20] [13 16 19]
]

random-room: does [random 20]
random-direction: does [random 3]

get-num: func [prompt][
	if error? try [return to integer! ask prompt] [
		return 0
	]
]

print-instructions: does [
	print {
WELCOME TO 'HUNT THE WUMPUS' (love that all caps retro look)

THE WUMPUS LIVES IN A CAVE OF 20 ROOMS. EACH ROOM HAS 3 TUNNELS LEADING TO
OTHER ROOMS.

HAZARDS:
  BOTTOMLESS PITS - TWO ROOMS HAVE BOTTOMLESS PITS IN THEM. IF YOU GO THERE,
    YOU FALL INTO THE PIT (YOU LOSE!)
  SUPER BATS - TWO OTHER ROOMS HAVE SUPER BATS. IF YOU GO THERE, A BAT GRABS
    YOU AND TAKES YOU TO SOME OTHER ROOM AT RANDOM. (WHICH MAY BE TROUBLESOME)

WUMPUS: THE WUMPUS IS NOT BOTHERED BY HAZARDS (HE HAS SUCKER FEET AND IS TOO
    BIG FOR A BAT TO LIFT). USUALLY HE IS ASLEEP. TWO THINGS WAKE HIM UP: YOU
    SHOOTING AN ARROW OR YOU ENTERING HIS ROOM. IF THE WUMPUS WAKES HE MOVES
    ONE ROOM (75% chance) OR STAYS STILL (25% chance). AFTER THAT, IF HE IS
    WHERE YOU ARE, HE EATS YOU UP AND YOU LOSE!

YOU: EACH TURN YOU MAY MOVE OR SHOOT A CROOKED ARROW.
  MOVING: YOU CAN MOVE ONE ROOM (THROUGH ONE TUNNEL).
  ARROWS: YOU HAVE 5 ARROWS.  YOU LOSE WHEN YOU RUN OUT.
        EACH ARROW CAN GO FROM 1 TO 5 ROOMS. YOU AIM BY TELLING THE COMPUTER
        THE ROOMS YOU WANT THE ARROW TO GO TO. IF THE ARROW CAN'T GO THAT WAY
        (I.E. NO TUNNEL) IT MOVES AT RANDOM TO THE NEXT ROOM.
        * IF THE ARROW HITS THE WUMPUS, YOU WIN.
        * IF THE ARROW HITS YOU, YOU LOSE.

WARNINGS: WHEN YOU ARE ONE ROOM AWAY FROM A WUMPUS OR HAZARD, THE COMPUTER SAYS:
    WUMPUS:  'YOU SMELL SOMETHING TERRIBLE NEARBY'
    BAT   :  'YOU HEAR A RUSTLING'
    PIT   :  'YOU FEEL A COLD WIND BLOWING FROM A NEARBY CAVERN'
}

	ask "Press <Enter> when you're ready to start the game"

]

check-for-hazards: has [i][
	print ""
	print ["You are in room" loc/:player]
	print ["Tunnels lead to" pick cave loc/:player]
	; Look at each of the 3 rooms around the player to see if the contain
	; the wumpus, a pit, or bats.
	repeat i 3 [
		room: pick pick cave loc/:player i
		if (room = loc/:wumpus) [
			print "^-You smell something terrible nearby."
		]
		if any [(room = loc/:pit-1) (room = loc/:pit-2)] [
			print "^-You feel a cold wind blowing from a nearby cavern."
		]
		if any [(room = loc/:bats-1) (room = loc/:bats-2)] [
			print "^-You hear a rustling."
		]
	]
	print ""
]

move-or-shoot?: has [cmd][
	cmd: ask "Shoot or move (S/M)? "
	; The default case handles bad inputs and prompts the user again.
	switch/default cmd [
		"S" ['shoot]
		"M" ['move]
	][move-or-shoot?]
]

move-arrow: func [room path /local i rnd-rm][
	;print reduce ["move arrow" room tab path]	; FOR DEBUG USE
	if not tail? path [
		; If they gave us a bogus target room, pick a random one.
		either find cave/:room first path [
			; Next room in path is valid
			check-for-arrow-hit first path
			if finished [exit]
			; Recursive call
			move-arrow first path next path
		][
			; Pick a random direction
			i: random-direction
			check-for-arrow-hit rnd-rm: cave/:room/:i
			if finished [exit]
			; Recursive call
			move-arrow rnd-rm next path
		]
	]
]

shoot: has [path][
	path: load ask "Enter 1 to 5 room numbers for the arrow's path: "
	path: compose [(path)]			; ensure it's a block, in case they entered only 1 number
	move-arrow loc/:player path
	if not finished [
		print "^-Your arrow missed"
		move-wumpus
	]
	; See if the Wumpus moved onto the player
	if finished [exit]

	arrow-count: arrow-count - 1
	if (arrow-count <= 0) [
		print "^/You ran out of arrows..."
		winner: 'wumpus
		finished: true
		exit
	]

	check-for-hazards
]

check-for-arrow-hit: func [room][
	if (room = loc/:wumpus) [
		print "^/You got the Wumpus!"
		winner: 'player
		finished: true
		exit
	]
	if (room = loc/:player) [
		print "^/You shot yourself!"
		winner: 'arrow
		finished: true
		exit
	]
]

; 75% chance that it will move
wumpus-moves?: does [either (random 4) < 4 [true][false]]

move-wumpus: does [
	if wumpus-moves? [loc/2: pick (pick cave loc/:wumpus) random-direction]
	if (loc/:wumpus = loc/:player) [
		winner: 'wumpus
		finished: true
	]
]

move-player: func [/bat-move new-loc /local new-player-loc][
	either bat-move [
		loc/1: new-loc
	][
		new-player-loc: get-num "To which room? "
		; Call recursively, then bail, if bad input
		if any [(new-player-loc < 1) (new-player-loc > 20)] [
			move-player
			exit
		]
		; Call recursively, then bail, if illegal move
		if not find pick cave loc/:player new-player-loc [
			print "You can't move there, if not you plan to dig a new tunnel."
			move-player
			exit
		]
		; It was a legal move, so update the player's location.
		change at loc player new-player-loc
	]

	if (loc/:player = loc/:wumpus) [
		print "Yikes! You bumped the Wumpus!"
		move-wumpus
		; See if the Wumpus moved onto the player
		if finished [exit]
	]
	if any [(loc/:player = loc/:pit-1) (loc/:player = loc/:pit-2) ] [
		print reduce [newline "Aaiiiiieeeee....(you fell in a pit)"]
		winner: 'pit
		finished: true
		exit
	]
	if any [(loc/:player = loc/:bats-1) (loc/:player = loc/:bats-2) ] [
		print "ZAP! Super-Bat snatch! Elsewhereville for you!"
		move-player/bat-move random-room
		exit
	]

	check-for-hazards

]

; This is ugly, but it works for now and avoids setup collisions.
; Don't really need items for this, but I'd like to improve it and then I might.
init-locations: has [items avail-rooms result offset][
	random/seed now/time/precise
	items: [player wumpus pit-1 pit-2 bats-1 bats-2]
	avail-rooms: copy [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20]
	result: make block! length? items
	repeat i length? items [
		; Too dense for one line?
		;append result pick avail-rooms offset: random length? avail-rooms
		offset: random/secure length? avail-rooms
		append result pick avail-rooms offset
		remove at avail-rooms offset
	]
	return result
]

setup: func [/same-as-last][
	; Initialize arrow count.
	arrow-count: 5
	; If we haven't setup before, or they want the same setup,
	; there's no need to initialize.
	if any [(not same-as-last) (start-loc = none)] [
		; Randomly place bats, pits, wumpus, and player
		start-loc: init-locations
	]
	; Make a working copy of the starting locations.
	loc: copy start-loc
]

do-game: func [/same-as-last][
	either same-as-last [
		setup/same-as-last
	][
		setup
	]
	check-for-hazards
	while [not finished][
		either move-or-shoot? = 'shoot [shoot][move-player]
	]
	print switch winner [
		wumpus ["<SNARF> The Wumpus got you!!!"]
		player ["<BLARP> The Wumpus will get you next time!"]
		pit    ["<SPLAT> Better luck next time"]
		arrow  ["<GLURG> You really should be more careful"]
	]
	print ""
]

start: does [
	if (ask "Would you like instructions (Y/N)? ") = "Y" [
		print-instructions
	]
	play: "Y"
	same-setup: "N"
	while [play = "Y"][
		either same-setup = "N" [
			do-game
		][
			do-game/same-as-last
		]
		play: ask "Play again (Y/N)? "
		if play = "Y" [
			winner: none
			finished: false
			same-setup: ask "Same setup (Y/N)? "
		]
	]
	halt
]

start


-- HUNT THE WUMPUS
--  BY GREGORY YOB
-- SenseTalk adaptation by Jonathan Gover

answer "INSTRUCTIONS (Y-N)" with "No" or "Yes"
if it is "Yes" then showInstructions

-- SET UP CAVE (DODECAHEDRAL NODE LIST)
set rooms to [
	[2,5,8],[1,3,10],[2,4,12],[3,5,14],[1,4,6],
	[5,7,15],[6,8,17],[1,7,9],[8,10,18],[2,9,11],
	[10,12,19],[3,11,13],[12,14,20],[4,13,15],[6,14,16],
	[15,17,20],[7,16,18],[9,17,19],[11,18,20],[13,16,19]
]

-- LOCATE L ARRAY ITEMS
set locations to the randomLocations
set initialLocations to locations

repeat
	-- SET# ARROWS
	set arrowCount to 5

	-- RUN THE GAME
	put "HUNT THE WUMPUS"

	repeat
		-- HAZARD WARNINGS & LOCATION
		locationAndHazardWarnings locations, rooms

		-- MOVE OR SHOOT
		answer "SHOOT OR MOVE (S-M)" with "Move" or "Shoot" or "Quit"
		if it is "Quit" then exit all

		-- SHOOT
		if it is "Shoot" then
			shoot reference to locations, rooms, reference to arrowCount
			winOrLose the result
			if the result isn't empty then exit repeat
		end if

		-- MOVE
		if it is "Move" then
			move reference to locations, rooms
			winOrLose the result
			if the result isn't empty then exit repeat
		end if

	end repeat

	answer "PLAY AGAIN? (Y-N)" with "No" or "Yes"
	if it is "No" then exit repeat

	answer "SAME SET-UP (Y-N)" with "No" or "Yes"
	if it is "Yes" then
		set locations to initialLocations
	else
		set locations to the randomLocations
		set initialLocations to locations
	end if

end repeat

to handle randomLocations
	put 1..20 shuffled into potentialLocations

	set locations to {
		player:first item of potentialLocations,
		wumpus:second item of potentialLocations,
		pits:third to fourth items of potentialLocations,
		bats:fifth to sixth items of potentialLocations
	}
	return locations
end randomLocations

to handle winOrLose result
	if result is "lose" then put "HA HA HA - YOU LOSE!"
	if result is "win" then put "HEE HEE HEE - THE WUMPUS'LL GETCHA NEXT TIME!!"
	return result
end winOrLose

-- INSTRUCTIONS
to handle showInstructions
	answer {{
WELCOME TO 'HUNT THE WUMPUS'
  THE WUMPUS LIVES IN A CAVE OF 20 ROOMS. EACH ROOM
HAS 3 TUNNELS LEADING TO OTHER ROOMS. (LOOK AT A
DODECAHEDRON TO SEE HOW THIS WORKS-IF YOU DON'T KNOW
WHAT A DODECAHEDRON IS, ASK SOMEONE)

     HAZARDS:
 BOTTOMLESS PITS - TWO ROOMS HAVE BOTTOMLESS PITS IN THEM
     IF YOU GO THERE, YOU FALL INTO THE PIT (& LOSE!)
 SUPER BATS - TWO OTHER ROOMS HAVE SUPER BATS. IF YOU
     GO THERE, A BAT GRABS YOU AND TAKES YOU TO SOME OTHER
     ROOM AT RANDOM. (WHICH MIGHT BE TROUBLESOME)

     WUMPUS:
 THE WUMPUS IS NOT BOTHERED BY THE HAZARDS (HE HAS SUCKER
 FEET AND IS TOO BIG FOR A BAT TO LIFT).  USUALLY
 HE IS ASLEEP. TWO THINGS WAKE HIM UP: YOUR ENTERING
 HIS ROOM OR YOUR SHOOTING AN ARROW.
     IF THE WUMPUS WAKES, HE MOVES (P=.75) ONE ROOM
 OR STAYS STILL (P=.25). AFTER THAT, IF HE IS WHERE YOU
 ARE, HE EATS YOU UP (& YOU LOSE!)

     YOU:
 EACH TURN YOU MAY MOVE OR SHOOT A CROOKED ARROW
   MOVING: YOU CAN GO ONE ROOM (THRU ONE TUNNEL)
   ARROWS: YOU HAVE 5 ARROWS. YOU LOSE WHEN YOU RUN OUT.
   EACH ARROW CAN GO FROM 1 TO 5 ROOMS. YOU AIM BY TELLING
   THE COMPUTER THE ROOM#S YOU WANT THE ARROW TO GO TO.
   IF THE ARROW CAN'T GO THAT WAY (IE NO TUNNEL) IT MOVES
   AT RANDOM TO THE NEXT ROOM.
     IF THE ARROW HITS THE WUMPUS, YOU WIN.
     IF THE ARROW HITS YOU, YOU LOSE.

    WARNINGS:
     WHEN YOU ARE ONE ROOM AWAY FROM WUMPUS OR HAZARD,
    THE COMPUTER SAYS:
 WUMPUS-  'I SMELL A WUMPUS'
 BAT   -  'BATS NEARBY'
 PIT   -  'I FEEL A DRAFT'

}}
end showInstructions

-- PRINT LOCATION & HAZARD WARNINGS
to handle locationAndHazardWarnings locations, rooms
	put empty

	set currentRoomNumber to locations.player
	set tunnelsLeadingTo to item currentRoomNumber of rooms

	repeat with each item of tunnelsLeadingTo
		if it is locations.wumpus then put "I SMELL A WUMPUS!"
		if it is in locations.pits then put "I FEEL A DRAFT"
		if it is in locations.bats then put "BATS NEARBY!"
	end repeat

	put !"YOU ARE IN ROOM [[currentRoomNumber]]"
	put !"TUNNELS LEAD TO [[tunnelsLeadingTo joined by space]]"
	put empty

end locationAndHazardWarnings

-- ARROW ROUTINE
to handle shoot locations, rooms, arrowCount
	-- PATH OF ARROW
	answer "NO. OF ROOMS(1-5)" from list 1..5
	set numberOfRooms to it

	set intendedPath to []

	repeat until the number of items in intendedPath equals numberOfRooms
		answer "ROOM #" from list 1..20
		set nextRoom to it

		if the number of items in intendedPath is more than 1
			if nextRoom equals the penultimate item in intendedPath
				put "ARROWS AREN'T THAT CROOKED - TRY ANOTHER ROOM"
				next repeat
			end if
		end if

		insert nextRoom into intendedPath

	end repeat

	-- SHOOT ARROW
	set arrowLocation to locations.player

	repeat with pathIndex from 1 to number of items in intendedPath
		set nextRoom to item pathIndex of intendedPath
		set tunnelsLeadingTo to item arrowLocation of rooms

		if tunnelsLeadingTo contains nextRoom then
			set arrowLocation to nextRoom
		else
			-- NO TUNNEL FOR ARROW
			set arrowLocation to any item of tunnelsLeadingTo
		end if

		-- SEE IF ARROW IS AT L(1) OR L(2)
		if arrowLocation equals locations.wumpus then
			put "AHA! YOU GOT THE WUMPUS!"
			return "win"
		end if

		if arrowLocation equals locations.player then
			put "OUCH! ARROW GOT YOU!"
			return "lose"
		end if

		put "MISSED"

		-- MOVE WUMPUS
		moveWumpus reference to locations, rooms
		if the result is "lose" then return "lose"

		-- AMMO CHECK
		subtract 1 from arrowCount
		if arrowCount is 0 then
			put "NO ARROWS LEFT"
			return "lose"
		end if
	end repeat

end shoot

-- MOVE WUMPUS ROUTINE
to handle moveWumpus locations, rooms
	if random of 4 isn't 4 then
		set currentRoomNumber to locations.wumpus
		set tunnelsLeadingTo to item currentRoomNumber of rooms

		set locations.wumpus to any item of tunnelsLeadingTo
	end if

	if locations.player equals locations.wumpus then
		put "TSK TSK TSK- WUMPUS GOT YOU!"
		return "lose"
	end if

	return empty
end moveWumpus

-- MOVE ROUTINE
to handle move locations, rooms
	set currentRoomNumber to locations.player
	set tunnelsLeadingTo to item currentRoomNumber of rooms

	answer "WHERE TO" from list tunnelsLeadingTo
	set locations.player to it

	-- CHECK FOR HAZARDS
	-- WUMPUS
	if locations.player equals locations.wumpus then
		put "...OOPS! BUMPED A WUMPUS!"

		-- MOVE WUMPUS
		moveWumpus reference to locations, rooms
		if the result is "lose" then return "lose"
	end if

	-- PIT
	if locations.pits contains locations.player then
		put "YYYIIIIEEEE . . . FELL IN PIT"
		return "lose"
	end if

	-- BATS
	if locations.bats contains locations.player then
		put "ZAP--SUPER BAT SNATCH! ELSEWHEREVILLE FOR YOU!"
		set locations.player to any item of 1..20
	end if
end move


import "/big" for BigInt

var countryCodes =
    "AD24 AE23 AL28 AT20 AZ28 BA20 BE16 BG22 BH22 BR29 " +
    "BY28 CH21 CR22 CY28 CZ24 DE22 DK18 DO28 EE20 ES24 " +
    "FI18 FO18 FR27 GB22 GE22 GI23 GL18 GR27 GT28 HR21 " +
    "HU28 IE22 IL23 IQ23 IS26 IT27 JO30 KW30 KZ20 LB28 " +
    "LC32 LI21 LT20 LU20 LV21 MC27 MD24 ME22 MK19 MR27 " +
    "MT31 MU30 NL18 NO15 PK24 PL28 PS29 PT25 QA29 RO24 " +
    "RS22 SA24 SC31 SE24 SI19 SK24 SM27 ST25 SV28 TL23 " +
    "TN24 TR26 UA29 VG24 XK20"

var isValid = Fn.new { |iban|
    // remove spaces from IBAN
    var s = iban.replace(" ", "")

    // check country code and length
    if (!countryCodes.contains(s[0..1] + s.count.toString)) return false

    // move first 4 characters to the end
    s = s[4..-1] + s[0..3]

    // replace A to Z with numbers 10 To 35
    var i = 10
    for (c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ") {
        s = s.replace(c, i.toString)
        i = i + 1
    }

    // check whether mod 97 calculation gives a remainder of 1
    return (BigInt.new(s) % BigInt.new(97)) == BigInt.one
}

var ibans = [ "GB82 WEST 1234 5698 7654 32", "GB82 TEST 1234 5698 7654 32" ]
for (iban in ibans) {
    var valid = isValid.call(iban)
    System.print(iban + (valid ? " may be valid" : " is not valid"))
}


// List updated to release 72, 25 November 2016, of IBAN Registry (75 countries)
countryCodes$ = "AD24 AE23 AL28 AT20 AZ28 BA20 BE16 BG22 BH22 BR29 BY28 CH21 CR22 CY28 CZ24 DE22 "
countryCodes$ = countryCodes$ + "DK18 DO28 EE20 ES24 FI18 FO18 FR27 GB22 GE22 GI23 GL18 GR27 GT28 HR21 HU28 IE22 "
countryCodes$ = countryCodes$ + "IL23 IQ23 IS26 IT27 JO30 KW30 KZ20 LB28 LC32 LI21 LT20 LU20 LV21 MC27 MD24 ME22 "
countryCodes$ = countryCodes$ + "MK19 MR27 MT31 MU30 NL18 NO15 PK24 PL28 PS29 PT25 QA29 RO24 RS22 SA24 SC31 SE24 "
countryCodes$ = countryCodes$ + "SI19 SK24 SM27 ST25 SV28 TL23 TN24 TR26 UA29 VG24 XK20"

sub iban(code$)
// This routine does and should reject codes containing spaces etc.
// Use iban_s() below for otherwise.
    local country, lcode, c, i, ch$

    lcode = len(code$)
    country = instr(countryCodes$, upper$(left$(code$, 2)))

    if country and lcode = val(mid$(countryCodes$, country + 2, 2)) then
        code$ = right$(code$, lcode - 4) + left$(code$, 4)
        for i = 1 to lcode
            ch$ = mid$(code$, i, 1)
            if ch$ >= "0" and ch$ <= "9" then
                c = c * 10 + asc(ch$) - asc("0")
            elsif ch$ >= "A" and ch$ <= "Z" then
                c = c * 100 + asc(ch$) - 55
            else
                return false
            end if
            c = mod(c, 97)
        next i
        return c = 1
    end if
    return false
end sub

sub iban_s(code$)
// strips any embedded spaces and hyphens before validating.
	local i, t$(1), n

	i = token(code$, t$(), " -")
	code$ = ""
	for n = 1 to i
		code$ = code$ + t$(n)
	next n

    return iban(code$)
end sub

sub test(code$, expected)
    local valid, state$

    valid = iban_s(code$)

    if valid = expected then
    	if valid then
    		state$ = "ok"
    	else
    		state$ = "invalid (as expected)"
    	end if
    else
    	if valid then
    		state$ = "OK!!"
    	else
    		state$ = "INVALID!!"
    	end if
    	state$ = state$ + " (NOT AS EXPECTED)"
    end if
    print code$, "\t ", state$
end sub

test("GB82 WEST 1234 5698 7654 32", true)
test("GB82 TEST 1234 5698 7654 32", false)
test("GB81 WEST 1234 5698 7654 32", false)
test("SA03 8000 0000 6080 1016 7519", true)
test("CH93 0076 2011 6238 5295 7", true)


(ns i-before-e.core
  (:require [clojure.string :as s])
  (:gen-class))

(def patterns {:cie #"cie" :ie #"(?<!c)ie" :cei #"cei" :ei #"(?<!c)ei"})

(defn update-counts
  "Given a map of counts of matching patterns and a word, increment any count if the word matches it's pattern."
  [counts [word freq]]
  (apply hash-map (mapcat (fn [[k v]] [k (if (re-seq (patterns k) word) (+ freq v) v)]) counts)))

(defn count-ie-ei-combinations
  "Update counts of all ie and ei combinations"
  [words]
  (reduce update-counts {:ie 0 :cie 0 :ei 0 :cei 0} words))

(defn apply-freq-1
  "Apply a frequency of one to words"
  [words]
  (map #(vector % 1) words))

(defn- format-plausible
  [plausible?]
  (if plausible? "plausible" "implausible"))

(defn- apply-rule [desc examples contra]
  (let [plausible? (<= (* 2 contra) examples)]
    (println (format "The sub rule %s is %s. There are %d examples and %d counter-examples.\n" desc (format-plausible plausible?) examples contra))
    plausible?))

(defn i-before-e-except-after-c-plausible?
  "Check if i before e after c plausible?"
  [description words]
  (do
    (println description)
    (let [counts (count-ie-ei-combinations words)
          subrule1 (apply-rule "I before E when not preceeded by C" (:ie counts) (:ei counts))
          subrule2 (apply-rule "E before I when preceeded by C" (:cei counts) (:cie counts))
          rule (and subrule1 subrule2)]
      (println (format "Overall the rule 'I before E except after C' is %s" (format-plausible rule)))
      rule)))

(defn format-freq-line [line] (letfn [(format-line [xs] [(first xs) (read-string (last xs))])]
                                       (-> line
                                           s/trim
                                           (s/split #"\s")
                                           format-line)))

(defn -main []
  (with-open [rdr (clojure.java.io/reader "http://wiki.puzzlers.org/pub/wordlists/unixdict.txt")]
   (i-before-e-except-after-c-plausible? "Check unixdist list" (apply-freq-1 (line-seq rdr))))
  (with-open [rdr (clojure.java.io/reader "http://ucrel.lancs.ac.uk/bncfreq/lists/1_2_all_freq.txt")]
   (i-before-e-except-after-c-plausible? "Word frequencies (stretch goal)" (map format-freq-line (drop 1 (line-seq rdr))))))


#include <iomanip>
#include <iostream>
#include <map>
#include <sstream>

bool isHumble(int i) {
    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;
}

auto toString(int n) {
    std::stringstream ss;
    ss << n;
    return ss.str();
}

int main() {
    auto limit = SHRT_MAX;
    std::map<int, int> humble;
    auto count = 0;
    auto num = 1;

    while (count < limit) {
        if (isHumble(num)) {
            auto str = toString(num);
            auto len = str.length();
            auto it = humble.find(len);

            if (it != humble.end()) {
                it->second++;
            } else {
                humble[len] = 1;
            }

            if (count < 50) std::cout << num << ' ';
            count++;
        }
        num++;
    }
    std::cout << "\n\n";

    std::cout << "Of the first " << count << " humble numbers:\n";
    num = 1;
    while (num < humble.size() - 1) {
        auto it = humble.find(num);
        if (it != humble.end()) {
            auto c = *it;
            std::cout << std::setw(5) << c.second << " have " << std::setw(2) << num << " digits\n";
            num++;
        } else {
            break;
        }
    }

    return 0;
}


#!/usr/local/bin/shale

// This is an implementation of the old game called Hunt the Wumpus.
//
// You can read about it here: https://en.wikipedia.org/wiki/Hunt_the_Wumpus
//
// Here's a quick summary:
//
// You are in a maze of 20 rooms, numbered 1 through 20. Each room is connected to
// 3 other rooms. There is no light in the maze, and the game will tell you which
// rooms are connected to the one you're in. The maze layout and numbering is the
// same for every game. At the time of writing, the Wikipedia page above has an
// image showing the layout and numbering.
//
// In the maze is a Wumpus, 2 bottomless pits and 2 super bats. You will die if you
// are in the same room as the Wumpus or if you fall into one of the pits.
// If you enter a room where a super bat is you will be transported to another
// random room.
//
// You can move about the maze by entering one of the connecting rooms.
// If a connecting room contains the Wumpus, a pit or a super bat, the game
// will let you know that they are around but not which room they are in.
//
// To win you need to kill the Wumpus. You have 5 arrows at your disposal that
// may be shot through up to 5 connected rooms, and if your arrow passes through
// the room containing the Wumpus then it dies and you win. If your arrow
// misses it will wake the Wumpus up and it will move randomly through the maze.

maths library
file library
string library

playerRoom var
wumpusRoom var
pit1Room var
pit2Room var
bat1Room var
bat2Room var
arrows var
wumpusIsAwake var
showStats var
statPlayer var
statWumpus var
statPit var
statArrow var

haveWon var
haveDied var

// Initialises the maze.
init dup var {
  i dup var 1 =

  { i 20 <= } {
    0 i.value:: room:: var
    1 i.value:: room:: var
    2 i.value:: room:: var
    i++
  } while

  0  1:: room::  2 =
  1  1:: room::  5 =
  2  1:: room::  8 =
  0  2:: room::  1 =
  1  2:: room::  3 =
  2  2:: room:: 10 =
  0  3:: room::  2 =
  1  3:: room::  4 =
  2  3:: room:: 12 =
  0  4:: room::  3 =
  1  4:: room::  5 =
  2  4:: room:: 14 =
  0  5:: room::  1 =
  1  5:: room::  4 =
  2  5:: room::  6 =
  0  6:: room::  5 =
  1  6:: room::  7 =
  2  6:: room:: 15 =
  0  7:: room::  6 =
  1  7:: room::  8 =
  2  7:: room:: 17 =
  0  8:: room::  1 =
  1  8:: room::  7 =
  2  8:: room::  9 =
  0  9:: room::  8 =
  1  9:: room:: 10 =
  2  9:: room:: 18 =
  0 10:: room::  2 =
  1 10:: room::  9 =
  2 10:: room:: 11 =
  0 11:: room:: 10 =
  1 11:: room:: 12 =
  2 11:: room:: 19 =
  0 12:: room::  3 =
  1 12:: room:: 11 =
  2 12:: room:: 13 =
  0 13:: room:: 12 =
  1 13:: room:: 14 =
  2 13:: room:: 20 =
  0 14:: room::  4 =
  1 14:: room:: 13 =
  2 14:: room:: 15 =
  0 15:: room::  6 =
  1 15:: room:: 14 =
  2 15:: room:: 16 =
  0 16:: room:: 15 =
  1 16:: room:: 17 =
  2 16:: room:: 20 =
  0 17:: room::  7 =
  1 17:: room:: 16 =
  2 17:: room:: 18 =
  0 18:: room::  9 =
  1 18:: room:: 17 =
  2 18:: room:: 19 =
  0 19:: room:: 11 =
  1 19:: room:: 18 =
  2 19:: room:: 20 =
  0 20:: room:: 13 =
  1 20:: room:: 16 =
  2 20:: room:: 19 =
} =

// Couple of funciton to return various random numbers needed
// for different tasks.
getRandomRoom dup var {
  random maths::() 8 >> 20 % 1 +
} =

getRandomConnectingRoom dup var {
  random maths::() 12 >> 3 % swap :: room:: value
} =

getRandomWumpusMove dup var {
  random maths::() 8 >> 4 % 0 >       // 3 in 4 chance the Wumpus moves.
} =

// Randomise the starting locations.
chooseStartingRooms dup var {
  playerRoom getRandomRoom() =
  wumpusRoom getRandomRoom() =
  { wumpusRoom playerRoom == } {
    wumpusRoom getRandomRoom() =
  } while
  pit1Room getRandomRoom() =
  pit1Room playerRoom == { pit1Room wumpusRoom == } or {
    pit1Room getRandomRoom() =
  } ifthen
  pit2Room getRandomRoom() =
  pit2Room playerRoom == { pit2Room wumpusRoom == { pit2Room pit1Room == } or } or {
    pit2Room getRandomRoom() =
  } ifthen
  bat1Room getRandomRoom() =
  bat1Room playerRoom == { bat1Room wumpusRoom == } or {
    bat1Room getRandomRoom() =
  } ifthen
  bat2Room getRandomRoom() =
  bat2Room playerRoom == { bat2Room wumpusRoom == { bat2Room bat1Room == } or } or {
    bat2Room getRandomRoom() =
  } ifthen
} =

// Details the connected rooms and whether the Wumpus, a pit or a bat is in a connected room.
showPlayerRoom dup var {
  pitNearby dup var false =
  batsNearby dup var false =

  2 playerRoom.value:: room:: 1 playerRoom.value:: room:: 0 playerRoom.value:: room:: playerRoom "You are in room %d, with connections to rooms %d, %d and %d\n" printf
  0 playerRoom.value:: room:: wumpusRoom == { 1 playerRoom.value:: room:: wumpusRoom == { 2 playerRoom.value:: room:: wumpusRoom == } or } or {
    "You smell a dreadful stench!" println
  } ifthen
  0 playerRoom.value:: room:: pit1Room == { 1 playerRoom.value:: room:: pit1Room == { 2 playerRoom.value:: room:: pit1Room == } or } or {
    pitNearby true =
  } ifthen
  pitNearby not {
    0 playerRoom.value:: room:: pit2Room == { 1 playerRoom.value:: room:: pit2Room == { 2 playerRoom.value:: room:: pit2Room == } or } or {
      pitNearby true =
    } ifthen
  } ifthen
  pitNearby {
    "You feel a draft." println
  } ifthen
  0 playerRoom.value:: room:: bat1Room == { 1 playerRoom.value:: room:: bat1Room == { 2 playerRoom.value:: room:: bat1Room == } or } or {
    batsNearby true =
  } ifthen
  batsNearby not {
    0 playerRoom.value:: room:: bat2Room == { 1 playerRoom.value:: room:: bat2Room == { 2 playerRoom.value:: room:: bat2Room == } or } or {
      batsNearby true =
    } ifthen
  } ifthen
  batsNearby {
    "There are bats nearby." println
  } ifthen
  "" println
} =

getAnswer dup var {
  haveAnswer dup var false =

  { haveAnswer not } {
    stdin file:: fgets file::() {
      dup
      "xyzzy" equals string::() {
        showStats showStats not =
        pop
      } {
        atoi string::()
        haveAnswer true =
      } if
    } {
      0 exit
    } if
  } while
} =

// Handles the process of moving to a connected room.
move dup var {
  haveRoom dup var false =
  req var

  { haveRoom not } {
    2 playerRoom.value:: room:: 1 playerRoom.value:: room:: 0 playerRoom.value:: room:: "Move to room (%d, %d or %d): " printf
    req getAnswer() =
    req 0 playerRoom.value:: room:: == { req 1 playerRoom.value:: room:: == { req 2 playerRoom.value:: room:: == } or } or {
      playerRoom req =
      haveRoom true =
    } {
      "That is not a connected room." println
    } if
  } while
  "" println
} =

// Handles the process of shooting an arrow.
shoot dup var {
  haveAnswer var
  req var
  rooms var
  lastRoom var
  i var
  gotKilled var
  gotTheWumpus var

  "" println
  arrows 1 == { "" } { "s" } if arrows "You have %d arrow%s remaining.\n" printf
  "How many rooms will your arrow pass through (1 to 5): " print
  lastRoom playerRoom =
  gotKilled false =
  gotTheWumpus false =
  haveAnswer false =
  { haveAnswer not } {
    req getAnswer() =
    req 1 >= req 5 <= and {
      rooms req =
      haveAnswer true =
    } {
      "You must specify 1, 2, 3, 4 or 5." println
    } if
  } while

  i 1 =
  { i rooms <= } {
    haveAnswer false =
    { haveAnswer not } {
      2 lastRoom.value:: room:: 1 lastRoom.value:: room:: 0 lastRoom.value:: room::
      i rooms == {
        rooms 1 == { "Only room" } { "Last room" } if
      } {
        i 1 == { "1st room" } ifthen
        i 2 == { "2nd room" } ifthen
        i 3 == { "3rd room" } ifthen
        i 4 == { "4th room" } ifthen
      } if
      "%s (%d, %d or %d): " printf

      req getAnswer() =
      req 0 lastRoom.value:: room:: == { req 1 lastRoom.value:: room:: == { req 2 lastRoom.value:: room:: == } or } or {
        req playerRoom == {
          gotKilled true =
        } ifthen
        req wumpusRoom == {
          gotTheWumpus true =
        } ifthen
        lastRoom req =
        haveAnswer true =
      } ifthen
    } while

    i++
  } while
  arrows--

  "" println
  gotKilled {
    "You were killed by your own arrow." println
    haveDied true =
    statArrow++
  } {
    gotTheWumpus {
      "Congratulations, you killed the Wumpus." println
      haveWon true =
      statPlayer++
    } {
      arrows 0 == {
        "Your arrow missed and you have died because you have no arrows left." println
        haveDied true =
        statArrow++
      } {
        wumpusIsAwake {
          "Your arrow missed." println
        } {
          "Your arrow missed and you've woken up the Wumpus." println
          wumpusIsAwake true =
        } if
      } if
    } if
  } if
} =

// The player's turn, move or shoot.
playerTurn dup var {
  turnOver dup var false =
  req  var

  { turnOver not } {
    showPlayerRoom()
    "1 - move" println
    "2 - shoot" println
    "> " print
    req getAnswer() =
    req 1 == {
      move()
      turnOver true =
    } ifthen
    req 2 == {
      shoot()
      turnOver true =
    } ifthen
  } while
} =

// The game's turn, whether to move the Wumpus or not.
gameTurn dup var {
  wumpusIsAwake {
    getRandomWumpusMove() {
      wumpusRoom wumpusRoom.value getRandomConnectingRoom() =
    } ifthen
  } ifthen
} =

// Check if something bad happened to the player.
checkSituationAfterPlayerMove dup var {
  playerRoom wumpusRoom == {
    "You have died, eaten by the Wumpus." println
    haveDied true =
    statWumpus++
  } {
    playerRoom pit1Room == playerRoom pit2Room == or {
      "You have died by falling into a pit." println
      haveDied true =
      statPit++
    } ifthen
  } if
  haveDied not {
    playerRoom bat1Room == {
      playerRoom getRandomRoom() =
      { playerRoom bat1Room == playerRoom bat2Room == or } {
        playerRoom getRandomRoom() =
      } while
      bat1Room getRandomRoom() =
      { bat1Room playerRoom == bat1Room bat2Room == or } {
        bat1Room getRandomRoom() =
      } while
      playerRoom "You have been moved to room %d.\n" printf
      checkSituationAfterPlayerMove()
    } {
      playerRoom bat2Room == {
        playerRoom getRandomRoom() =
        { playerRoom bat1Room == playerRoom bat2Room == or } {
          playerRoom getRandomRoom() =
        } while
        bat2Room getRandomRoom() =
        { bat2Room playerRoom == bat2Room bat1Room == or } {
          bat2Room getRandomRoom() =
        } while
        playerRoom "You have been moved to room %d.\n" printf
        checkSituationAfterPlayerMove()
      } ifthen
    } if
  } ifthen
} =

// Check if something bad happened to the player.
checkSituationAfterGameMove dup var {
  playerRoom wumpusRoom == {
    "You have died, eaten by the Wumpus." println
    haveDied true =
    statWumpus++
  } ifthen
} =

// Take turns between the player and the game.
play dup var {
  haveWon false =
  haveDied false =
  wumpusIsAwake false =
  arrows 5 =

  chooseStartingRooms()
  "" println
  { haveWon not haveDied not and } {
    playerTurn()
    checkSituationAfterPlayerMove()
    haveWon not haveDied not and {
      gameTurn()
      checkSituationAfterGameMove()
    } ifthen
  } while
} =

toplevel dup var {
  haveAnswer var
  req var

  showStats false =
  statPlayer 0 =
  statWumpus 0 =
  statPit 0 =
  statArrow 0 =

  { true } {
    haveAnswer false =
    { haveAnswer not } {
      showStats {
        statArrow statPit statWumpus statPlayer "\nPlayer %d, Wumpus %d, Pit %d, Arrow %d\n" printf
      } ifthen

      "" println
      "1 - play game" println
      "2 - quit" println
      "> " print
      req getAnswer() =
      req 2 == {
        0 exit
      } ifthen
      req 1 == {
        haveAnswer true =
      } ifthen
    } while

    play()
  } while
} =

init()
toplevel()


import Foundation

//All rooms in cave
var cave: [Int:[Int]] = [
    1: [2, 3, 4],
    2: [1, 5, 6],
    3: [1, 7, 8],
    4: [1, 9, 10],
    5: [2, 9, 11],
    6: [2, 7, 12],
    7: [3, 6, 13],
    8: [3, 10, 14],
    9: [4, 5, 15],
    10: [4, 8, 16],
    11: [5, 12, 17],
    12: [6, 11, 18],
    13: [7, 14, 18],
    14: [8, 13, 19],
    15: [9, 16, 17],
    16: [10, 15, 19],
    17: [11, 20, 15],
    18: [12, 13, 20],
    19: [14, 16, 20],
    20: [17, 18, 19]
]

// initialize curr room, wumpus's room, bats room
var player: Int = 0, wumpus: Int = 0, bat1:Int = 0, bat2:Int = 0, pit1:Int = 0, pit2:Int = 0

//number of arrows left
var arrows = 5

//check if room is empty
func isEmpty(r:Int)->Bool {
    if r != player &&
       r != wumpus &&
       r != bat1 &&
       r != bat2 &&
       r != pit1 &&
       r != pit2 {
            return true
        }
        return false
}

//sense if theres bat/pit/wumpus in adjacent rooms
func sense(adj: [Int]) {
    var bat = false
    var pit = false
    for ar in adj {
        if ar == wumpus {
            print("You smell something terrible nearby.")
        }
        switch ar {
        case bat1, bat2:
            if !bat {
                print("You hear rustling.")
                bat = true
            }
        case pit1, pit2:
            if !pit {
                print("You feel a cold wind blowing from a nearby cavern.")
                pit = true
            }
        default:
            print("")
        }
    }
}

//check if there are more than 1 arrow then add plural to arrow message
func plural(n: Int)->String {
    if n != 1 {
        return "s"
    }
    return ""
}

func game() {

    //set current room to 1, start the game
    player = 1

    //wumpus, bats, pits will be in a random room - except start room
    wumpus = Int.random(in: 2..<21)
    bat1 = Int.random(in: 2..<21)

    //bat2 must be in different room to bat1
    while true {
        bat2 = Int.random(in: 2..<21)
        if bat2 != bat1 {
            break
        }
    }

    //pit1 and pit2 must be in different rooms from bats and each other
    while true {
        pit1 = Int.random(in: 2..<21)
        if pit1 != bat1 && pit1 != bat2 {
            break
        }
    }
    while true {
        pit2 = Int.random(in: 0..<21)
        if pit2 != bat1 && pit2 != bat2 && pit2 != pit1 {
            break
        }
    }

    //player session
    while true {
        print("\nYou are in room \(player) with \(arrows) arrow\(plural(n: arrows)) left\n")

        //list of adjacent rooms
        let adj = cave[player]!
        print("The adjacent rooms are \(adj)\n")

        //check adjacent rooms
        sense(adj: adj)

        //variable to keep track of next room player gonna choose
        var room: Int?
        while true {
            print("Choose an adjacent room: ")

            //validate the room player choose
            if let roomInput = Int(readLine()!) {
                room = roomInput
                if !adj.contains(room!) {
                    print("\ninvalid response, try again\n")
                    print("The adjacent rooms are \(adj)\n")
                } else {
                    break
                }
            } else {
                print("\ninvalid response, try again\n")
                print("The adjacent rooms are \(adj)\n")
            }
        }

        //initialize variable to store user input/action(shoot or walk)
        var action: String = ""

        //player action
        while true {
            print("Walk or shoot w/s: ")
            //validate the action player choose
            if var reply = readLine() {
                reply = reply.lowercased()
                if reply.count != 1 || (reply.count == 1 && Array(reply)[0] != "w" && Array(reply)[0] != "s") {
                    print("Invalid response, try again")
                } else {
                    //if valid store the action
                    action = Array(arrayLiteral: reply)[0]
                    break
                }
            } else {
                print("Invalid response, try again")
            }
        }

        if action == "w" {
            //if walk, set current room to selected room
            player = room!
            switch player {
                //if the selected room is wumpus/pit, player lose
                case wumpus:
                    print("You have been eaten by the wumpus and lost the game")
                    return
                case pit1, pit2:
                    print("You have fallen down a bottomless pit and lost the game!")
                    return
                //if the room has bat, player got transport to a random empty room
                case bat1, bat2:
                    while true {
                        room = Int.random(in: 2..<21)
                        if isEmpty(r: room!) {
                            print("A bat has transported you to a random empty room.")
                            player = room!
                            break
                        }
                    }
                default:
                    break
            }
        } else {
            //if player shoot to wumpus room, player win
            if room == wumpus {
                print("You have killed the wumpus and won the game!!")
                return
            } else {
                //chance player will miss the room with wumpus, wumpus will move to a different room
                let chance = Int.random(in: 0..<4)
                if chance > 0 {
                    wumpus = cave[wumpus]![Int.random(in: 0..<3)]
                    //if the room is the player room, player lost
                    if player == wumpus {
                        print("You have been eaten by the wumpus and lost the game!")
                        return
                    }
                }
            }
            //reduce arrow after shoot
            arrows-=1
            if arrows == 0 {
                print("You have run out of arrows and lost the game!")
                return
            }
        }
    }
}
game()


var BN=Import("zklBigNum");
fcn validateIBAN(iban){
   iban=iban-" \t";
   alphaNums.matches(iban) and (ibans.find(iban[0,2])==iban.len()) and
   ( BN((iban[4,*]+iban[0,4]).apply("toInt",36)) % 97 == 1 )
}


10 REM REM Used the following as official standard:
20 REM REM  http://www.cnb.cz/cs/platebni_styk/iban/download/EBS204.pdf
30 REM REM Pairs of ISO 3166 country code & expected IBAN length for this country
40 LET c$="AL28 AD24 AT20 AZ28 BE16 BH22 BA20 BR29 BG22 CR21 HR21 CY28 CZ24 DK18 DO28 EE20 "
50 LET c$=c$+"FO18 FI18 FR27 GE22 DE22 GI23 GR27 GL18 GT28 HU28 IS26 IE22 IL23 IT27 KZ20 KW30 "
60 LET c$=c$+"LV21 LB28 LI21 LT20 LU20 MK19 MT31 MR27 MU30 MC27 MD24 ME22 NL18 NO15 PK24 PS29 "
70 LET c$=c$+"PL28 PT25 RO24 SM27 SA24 RS22 SK24 SI19 ES24 SE24 CH21 TN24 TR26 AE23 GB22 VG24 "
80 LET e$=""
100 LET i$="GB82 WEST 1234 5698 7654 32": GO SUB 1000
110 LET i$="gb82 west 1234 5698 7654 32": GO SUB 1000
120 LET i$="GB82 TEST 1234 5698 7654 32": GO SUB 1000
130 LET i$="GR16 0110 1250 0000 0001 2300 695": GO SUB 1000
140 LET i$="IL62-0108-0000-0009-9999-999": GO SUB 1000
900 STOP
1000 REM IBAN check routine
1010 LET explen=0: LET lenc=LEN c$
1020 FOR i=1 TO lenc STEP 5
1030 IF i$( TO 2)=c$(i TO i+1) THEN LET explen=VAL c$(i+2 TO i+3): GO TO 2000
1040 NEXT i
2000 LET match=explen>0
2010 REM Continue if country code found
2020 IF NOT match THEN LET e$="country code: "+i$( TO 2): GO TO 3000
2030 REM Remove espace = convert to digital IBAN
2040 LET d$=""
2050 FOR i=1 TO LEN i$
2060 IF i$(i)>" " THEN LET d$=d$+i$(i)
2070 NEXT i
2080 LET match=explen=LEN d$
2090 REM Continue if length is correct
2100 IF NOT match THEN LET e$="code length, expected length: "+STR$ explen: GO TO 3000
2110 REM Create temporary string with country code appended
2120 LET t$=d$(5 TO )+d$(1 TO 2)
2130 REM Make big number, replacing letters by numbers using next conversion table: A=10 ... Z=35
2140 LET b$=""
2150 FOR i=1 TO LEN t$
2160 LET c= CODE t$(i)
2170 IF (c>64 AND c<91) THEN LET b$=b$+STR$ (c-55): GO TO 2200
2190 IF (c>47 AND c<58) THEN LET b$=b$+t$(i)
2200 NEXT i
2210 REM MOD 97 on bignum$+"00" and subtract result from 98 to obtain control number
2220 LET k$=b$+"00": GO SUB 4000
2230 LET kk=98-mod97
2240 REM Compare with control number in IBAN
2250 LET match=VAL i$(3 TO 4)=kk
2260 REM Continue if control number matches
2270 IF NOT match THEN LET e$="check digits, should be: "+STR$ kk: GO TO 3000
2280 REM Append kk to bignum$ and determine if MOD 97 results in 1
2285 LET k$="0"+STR$ kk
2290 LET k$=b$+k$(LEN k$-1 TO ): GO SUB 4000
2300 LET match=mod97=1
2310 REM Continue if mod 97
2320 IF NOT match THEN LET e$="result from modulo 97"
3000 IF match THEN PRINT "  ": GO TO 3100
3010 PRINT "in";: LET e$=" ***error!*** invalid "+e$
3100 PRINT "valid IBAN: ";i$;e$: LET e$=""
3110 RETURN
4000 REM Modulo 97
4010 LET mod97=0
4020 FOR i=1 TO LEN k$
4030 LET d$=STR$ (mod97)+k$(i)
4040 LET mod97=FN m(VAL (d$),97)
4050 NEXT i
4060 RETURN
5000 DEF FN m(a,b)=a-INT (a/b)*b: REM modulo


report = cluster is new, classify, results
    rep = record[cie, xie, cei, xei, words: int]

    new = proc () returns (cvt)
        return(rep${cie: 0, xie: 0, cei: 0, xei: 0, words: 0})
    end new

    classify = proc (r: cvt, word: string)
        r.words := r.words + 1
        if string$indexs("ie", word) ~= 0 then
            if string$indexs("cie", word) ~= 0
                then r.cie := r.cie + 1
                else r.xie := r.xie + 1
            end
        elseif string$indexs("ei", word) ~= 0 then
            if string$indexs("cei", word) ~= 0
                then r.cei := r.cei + 1
                else r.xei := r.xei + 1
            end
        end
    end classify

    stat = proc (s: stream, name: string, val: int)
        stream$puts(s, name)
        stream$puts(s, ": ")
        stream$putl(s, int$unparse(val))
    end stat

    plausible = proc (s: stream, feature: string, match, nomatch: int)
                returns (bool)
        stream$puts(s, feature)
        stream$puts(s, ": ")
        plaus: bool := 2 * match > nomatch;
        if ~plaus then stream$puts(s, "not ") end
        stream$putl(s, "plausible.");
        return(plaus)
    end plausible

    results = proc (r: cvt) returns (string)
        ss: stream := stream$create_output()
        stat(ss, "Amount of words", r.words)
        stat(ss, "CIE", r.cie)
        stat(ss, "xIE", r.xie)
        stat(ss, "CEI", r.cei)
        stat(ss, "xEI", r.xei)
        stream$putl(ss, "")
        xie_p: bool := plausible(ss, "I before E when not preceded by C", r.xie, r.cie)
        cei_p: bool := plausible(ss, "E before I when preceded by C", r.cei, r.xei)
        stream$puts(ss, "I before E, except after C: ")
        if ~(xie_p & cei_p) then stream$puts(ss, "not ") end
        stream$putl(ss, "plausible.")
        return(stream$get_contents(ss))
    end results
end report

lines = iter (s: stream) yields (string)
    while true do
        yield(stream$getl(s))
        except when end_of_file: break end
    end
end lines

start_up = proc ()
    po: stream := stream$primary_output()
    file: file_name := file_name$parse("unixdict.txt")
    fstream: stream := stream$open(file, "read")
    r: report := report$new()
    for line: string in lines(fstream) do
        report$classify(r, line)
    end
    stream$close(fstream)
    stream$puts(po, report$results(r))
end start_up


ie-npc = ei-npc = ie-pc = ei-pc = 0
for word of dict.toLowerCase!.match /\S+/g
    ++ie-npc if /(^|[^c])ie/.test word
    ++ei-npc if /(^|[^c])ei/.test word
    ++ie-pc if word.indexOf('cie') > -1
    ++ei-pc if word.indexOf('cei') > -1

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

console.log '(1) is%s plausible.', if p1 then '' else ' not'
console.log '(2) is%s plausible.', if p2 then '' else ' not'
console.log 'The whole phrase is%s plausible.', if p1 and p2 then '' else ' not'


(defun test-rule (rule-name examples counter-examples)
  (let ((plausible (if (> examples (* 2 counter-examples)) 'plausible 'not-plausible)))
    (list rule-name plausible examples counter-examples)))

(defun plausibility (result-string file parser)
  (let ((cei 0) (cie 0) (ie 0) (ei 0))
    (macrolet ((search-count (&rest terms)
                 (when terms
                   `(progn
                      (when (search ,(string-downcase (symbol-name (car terms))) word)
                        (incf ,(car terms) freq))
                      (search-count ,@(cdr terms))))))
      (with-open-file (stream file :external-format :latin-1)
        (loop :for raw-line = (read-line stream nil 'eof)
              :until (eq raw-line 'eof)
              :for line = (string-trim '(#\Tab #\Space) raw-line)
              :for (word freq) = (funcall parser line)
              :do (search-count cei cie ie ei))
        (print-result result-string cei cie ie ei)))))

(defun print-result (result-string cei cie ie ei)
  (let ((results (list (test-rule "I before E when not preceded by C" (- ie cie) (- ei cei))
                       (test-rule "E before I when preceded by C" cei cie))))
    (format t "~a:~%~{~{~2TThe rule \"~a\" is ~S. There were ~a examples and ~a counter-examples.~}~^~%~}~%~%~2TOverall the rule is ~S~%~%"
            result-string results (or (find 'not-plausible (mapcar #'cadr results)) 'plausible))))

(defun parse-dict (line) (list line 1))

(defun parse-freq (line)
  (list (subseq line 0 (position #\Tab line))
        (parse-integer (subseq line (position #\Tab line :from-end t)) :junk-allowed t)))

(plausibility "Dictionary" #p"unixdict.txt" #'parse-dict)
(plausibility "Word frequencies (stretch goal)" #p"1_2_all_freq.txt" #'parse-freq)


def humble?(i)
  return true if (i < 2)
  return humble?(i // 2) if (i % 2 == 0)
  return humble?(i // 3) if (i % 3 == 0)
  return humble?(i // 5) if (i % 5 == 0)
  return humble?(i // 7) if (i % 7 == 0)
  false
end

count, num = 0, 0_i64
digits = 10                        # max digits for humble numbers
limit  = 10_i64 ** 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) }


import std.conv;
import std.stdio;

bool isHumble(int i) {
    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;
}

void main() {
    auto limit = short.max;
    int[int] humble;
    auto count = 0;
    auto num = 1;

    while (count < limit) {
        if (isHumble(num)) {
            auto str = num.to!string;
            auto len = str.length;
            humble[len]++;
            if (count < 50) write(num, ' ');
            count++;
        }
        num++;
    }
    writeln('\n');

    writeln("Of the first ", count, " humble numbers:");
    num = 1;
    while (num < humble.length - 1) {
        if (num in humble) {
            auto c = humble[num];
            writefln("%5d have %2d digits", c, num);
            num++;
        } else {
            break;
        }
    }
}


import "random" for Random
import "/fmt" for Fmt
import "/ioutil" for Input
import "/str" for Str

var cave = {
     1: [ 2,  3,  4],  2: [ 1,  5,  6],  3: [ 1,  7,  8],  4: [ 1,  9, 10],
     5: [ 2,  9, 11],  6: [ 2,  7, 12],  7: [ 3,  6, 13],  8: [ 3, 10, 14],
     9: [ 4,  5, 15], 10: [ 4,  8, 16], 11: [ 5, 12, 17], 12: [ 6, 11, 18],
    13: [ 7, 14, 18], 14: [ 8, 13, 19], 15: [ 9, 16, 17], 16: [10, 15, 19],
    17: [11, 20, 15], 18: [12, 13, 20], 19: [14, 16, 20], 20: [17, 18, 19]
}

var player
var wumpus
var batt1
var bat2
var pit1
var pit2
var arrows = 5

var isEmpty = Fn.new { |r|
    if (r != player && r != wumpus && r != bat1 && r != bat2 && r != pit1 && r != pit2) {
        return true
    }
    return false
}

var sense = Fn.new { |adj|
    var bat = false
    var pit = false
    for (ar in adj) {
        if (ar == wumpus) System.print("You smell something terrible nearby.")
        if (ar == bat1 || ar == bat2) {
            if (!bat) {
                System.print("You hear a rustling.")
                bat = true
            }
        } else if (ar == pit1 || ar == pit2) {
            if (!pit) {
                System.print("You feel a cold wind blowing from a nearby cavern.")
                pit = true
            }
        }
    }
    System.print()
}

var plural = Fn.new { |n| (n != 1) ? "s" : "" }

var rand = Random.new()
player = 1
wumpus = rand.int(2, 21)
bat1   = rand.int(2, 21)
while (true) {
    bat2 = rand.int(2, 21)
    if (bat2 != bat1) break
}
while (true) {
    pit1 = rand.int(2, 21)
    if (pit1 != bat1 && pit1 != bat2) break
}
while (true) {
    pit2 = rand.int(2, 21)
    if (pit2 != bat1 && pit2 != bat2 && pit2 != pit1) break
}
while (true) {
    Fmt.print("\nYou are in room $d with $d arrow$s left", player, arrows, plural.call(arrows))
    var adj = cave[player]
    System.print("The adjacent rooms are %(adj)")
    sense.call(adj)
    var room = Input.intOpt("Choose an adjacent room : ", adj)
    var action = Str.lower(Input.option("Walk or shoot w/s : ", "wsWS"))
    if (action == "w") {
        player = room
        if (player == wumpus) {
            System.print("You have been eaten by the Wumpus and lost the game!")
            return
        } else if (player == pit1 || player == pit2) {
            System.print("You have fallen down a bottomless pit and lost the game!")
            return
        } else if (player == bat1 || player == bat2) {
            while (true) {
                room = rand.int(2, 20)
                if (isEmpty.call(room)) {
                    System.print("A bat has transported you to a random empty room")
                    player = room
                    break
                }
            }
        }
    } else {
        if (room == wumpus) {
            System.print("You have killed the Wumpus and won the game!!")
            return
        } else {
            var chance = rand.int(4) // 0 to 3
            if (chance > 0) {        // 75% probability
                wumpus = cave[wumpus][rand.int(3)]
                if (player == wumpus) {
                    System.print("You have been eaten by the Wumpus and lost the game!")
                    return
                }
            }
        }
        arrows = arrows - 1
        if (arrows == 0) {
            System.print("You have run out of arrows and lost the game!")
            return
        }
    }
}


import std.file;
import std.stdio;

int main(string[] args) {
    if (args.length < 2) {
        stderr.writeln(args[0], " filename");
        return 1;
    }

    int cei, cie, ie, ei;
    auto file = File(args[1]);
    foreach(line; file.byLine) {
        auto res = eval(cast(string) line);
        cei += res.cei;
        cie += res.cie;
        ei += res.ei;
        ie += res.ie;
    }

    writeln("CEI: ", cei, "; CIE: ", cie);
    writeln("EI: ", ei, "; IE: ", ie);

    writeln("'I before E when not preceded by C' is ", verdict(ie, ei));
    writeln("'E before I when preceded by C' is ", verdict(cei, cie));

    return 0;
}

string verdict(int a, int b) {
    import std.format;
    if (a > 2*b) {
        return format("plausible with evidence %f", cast(double)a/b);
    }
    return format("not plausible with evidence %f", cast(double)a/b);
}

struct Evidence {
    int cei;
    int cie;
    int ei;
    int ie;
}

Evidence eval(string word) {
    enum State {
        START,
        C,
        E,
        I,
        CE,
        CI,
    }

    State state;
    Evidence cnt;
    for(int i=0; i<word.length; ++i) {
        char c = word[i];
        switch(state) {
            case State.START:
                if (c == 'c') {
                    state = State.C;
                }
                if (c == 'e') {
                    state = State.E;
                }
                if (c == 'i') {
                    state = State.I;
                }
                break;
            case State.C:
                if (c == 'e') {
                    state = State.CE;
                } else if (c == 'i') {
                    state = State.CI;
                } else if (c != 'c') {
                    state = State.START;
                }
                break;
            case State.E:
                if (c == 'c') {
                    state = State.C;
                } else if (c == 'i') {
                    cnt.ei++;
                    state = State.I;
                } else if (c != 'e') {
                    state = State.START;
                }
                break;
            case State.I:
                if (c == 'c') {
                    state = State.C;
                } else if (c == 'e') {
                    cnt.ie++;
                    state = State.E;
                } else if (c != 'i') {
                    state = State.START;
                }
                break;
            case State.CE:
                if (c == 'i') {
                    cnt.cei++;
                    state = State.I;
                }
                if (c == 'c') {
                    state = State.C;
                }
                state = State.START;
                break;
            case State.CI:
                if (c == 'e') {
                    cnt.cie++;
                    state = State.E;
                }
                if (c == 'c') {
                    state = State.C;
                }
                state = State.START;
                break;
            default:
                assert(0);
        }
    }
    return cnt;
}


// Generate humble numbers. Nigel Galloway: June 18th., 2020
let     fN g=let mutable n=1UL in (fun()->n<-n*g;n)
let     fI (n:uint64) g=let mutable q=n in (fun()->let t=q in q<-n*g();t)
let     fG n g=let mutable vn,vg=n(),g() in fun()->match vg<vn with true->let t=vg in vg<-g();t |_->let t=vn in vn<-n();t
let rec fE n=seq{yield n();yield! fE n}
let     fL n g=let mutable vn,vg,v=n(),g(),None
               fun()->match v with
                       Some n->v<-None;n
                      |_->match vg() with
                           r when r<vn->r
                          |r->vg<-fG vg (fI vn (g()));vn<-n();v<-Some r;vg()
let humble = seq{yield 1UL;yield! fE(fL (fN 7UL) (fun()->fL (fN 5UL) (fun()->fL (fN 3UL) (fun()->fN 2UL))))}


program I_before_E_except_after_C;

uses
  System.SysUtils, System.IOUtils;

function IsOppPlausibleWord(w: string): Boolean;
begin
  if ((not w.Contains('c')) and (w.Contains('ei'))) then
    exit(True);

  if (w.Contains('cie')) then
    exit(True);

  exit(false);
end;

function IsPlausibleWord(w: string): Boolean;
begin
  if ((not w.Contains('c')) and (w.Contains('ie'))) then
    exit(True);

  if (w.Contains('cie')) then
    exit(True);

  exit(false);
end;

function IsPlausibleRule(filename: TFileName): Boolean;
var
  words: TArray<string>;
  trueCount, falseCount: Cardinal;
  w: string;
begin
  words := TFile.ReadAllLines(filename, TEncoding.UTF8);
  trueCount := 0;
  falseCount := 0;

  for w in words do
  begin
    if (IsPlausibleWord(w)) then
      inc(trueCount)
    else if (IsOppPlausibleWord(w)) then
      inc(falseCount);

  end;

  Writeln('Plausible count: ', trueCount);
  Writeln('Implausible  count: ', falseCount);

  Result := trueCount > 2 * falseCount;;

end;

begin
  if (IsPlausibleRule('unixdict.txt')) then
    Writeln('Rule is plausible.')
  else
    Writeln('Rule is not plausible.');

end.


USING: accessors assocs combinators deques dlists formatting fry
generalizations io kernel make math math.functions math.order
prettyprint sequences tools.memory.private ;
IN: rosetta-code.humble-numbers

TUPLE: humble-iterator 2s 3s 5s 7s digits
    { #digits initial: 1 } { target initial: 10 } ;

: <humble-iterator> ( -- humble-iterator )
    humble-iterator new
    1 1dlist >>2s
    1 1dlist >>3s
    1 1dlist >>5s
    1 1dlist >>7s
    H{ } clone >>digits ;

: enqueue ( n humble-iterator -- )
    {
        [ [ 2 * ] [ 2s>> ] ]
        [ [ 3 * ] [ 3s>> ] ]
        [ [ 5 * ] [ 5s>> ] ]
        [ [ 7 * ] [ 7s>> ] ]
    } [ bi* push-back ] map-compose 2cleave ;

: count-digits ( humble-iterator n -- )
    [ over target>> >=
    [ [ 1 + ] change-#digits [ 10 * ] change-target ] when ]
    [ drop 1 swap [ #digits>> ] [ digits>> ] bi at+ ] bi ;

: ?pop ( 2s 3s 5s 7s n -- )
    '[ dup peek-front _ = [ pop-front* ] [ drop ] if ] 4 napply ;

: next ( humble-iterator -- n )
    dup dup { [ 2s>> ] [ 3s>> ] [ 5s>> ] [ 7s>> ] } cleave
    4 ndup [ peek-front ] 4 napply min min min
    { [ ?pop ] [ swap enqueue ] [ count-digits ] [ ] } cleave ;

: upto-n-digits ( humble-iterator n -- seq )
    1 + swap [ [ 2dup digits>> key? ] [ dup next , ] until ] { }
    make [ digits>> delete-at ] dip but-last-slice ;

: .first50 ( seq -- )
    "First 50 humble numbers:" print 50 head [ pprint bl ] each
    nl ;

: .digit-breakdown ( humble-iterator -- )
    "The digit counts of humble numbers:" print digits>> [
        commas swap dup 1 = "" "s" ? "%9s have %2d digit%s\n"
        printf
    ] assoc-each ;

: humble-numbers ( -- )
    [ <humble-iterator> dup 95 upto-n-digits
    [ .first50 nl ] [ drop .digit-breakdown nl ] [
        "Total number of humble numbers found: " write length
        commas print
    ] tri ] time ;

MAIN: humble-numbers


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

Const limiteMax = 7574
Dim As Integer humble(10) 'As New Dictionary(Of Integer, Integer)
Dim As Integer cont = 0, num = 1

Print "Los 50 primeros n£meros de Humble son:";
While cont < limiteMax
    If IsHumble(num) Then
        Dim As Integer longitud = Len(Str(num))
        If longitud > 10 Then
            Exit While
        End If
        If humble(longitud) Then
            humble(longitud) += 1
        Else
            humble(longitud) = 1
        End If
        If cont < 50 Then
            If cont Mod 10 = 0 Then Print
            Print Using " ###"; num;
        End If
        cont += 1
    End If
    num += 1
Wend

Print !"\n\nDe los primeros"; cont; " n£meros de Humble:"
num = 1
While num < cont
    If humble(num) Then
        Print Using " #### tienen ## digitos"; humble(num); num
        num += 1
    Else
        Exit While
    End If
Wend


\util.g

/* variables to hold totals for each possibility */
word cie, xie, cei, xei;

/* classify a word and add it to the proper total */
proc nonrec classify(*char w) void:
    if CharsIndex(w, "ie") /= -1 then
        if CharsIndex(w, "cie") /= -1
            then cie := cie + 1
            else xie := xie + 1
        fi
    elif CharsIndex(w, "ei") /= -1 then
        if CharsIndex(w, "cei") /= -1
            then cei := cei + 1
            else xei := xei + 1
        fi
    fi
corp

/* see if a clause is plausible */
proc nonrec plausible(*char clause; word match, nomatch) bool:
    bool p;
    p := 2*match > nomatch;
    writeln(clause, ": ", if p then "" else "not " fi, "plausible.");
    p
corp

proc nonrec main() void:
    file() dict_file;
    channel input text dict_ch;
    [256] char line;
    bool p;

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

    /* read every word */
    open(dict_ch, dict_file, "unixdict.txt");
    while readln(dict_ch; &line[0]) do
        classify(&line[0])
    od;
    close(dict_ch);

    /* print statistics */
    writeln("CIE: ", cie:5);
    writeln("xIE: ", xie:5);
    writeln("CEI: ", cei:5);
    writeln("xEI: ", xei:5);

    /* see if the propositions are plausible */
    p := plausible("I before E when not preceded by C", xie, cie);
    p := plausible("E before I when preceded by C", cei, xei) and p;
    writeln("I before E except after C: ",
            if p then "" else "not " fi,
            "plausible.")
corp


defmodule RC do
  def task(path) do
    plausibility_ratio = 2
    rules = [ {"I before E when not preceded by C:", "ie", "ei"},
              {"E before I when preceded by C:", "cei", "cie"} ]
    regex = ~r/ie|ei|cie|cei/
    counter = File.read!(path) |> countup(regex)
    Enum.all?(rules, fn {str, x, y} ->
      nx = counter[x]
      ny = counter[y]
      ratio = nx / ny
      plausibility = if ratio > plausibility_ratio, do: "Plausible", else: "Implausible"
      IO.puts str
      IO.puts "  #{x}: #{nx}; #{y}: #{ny}; Ratio: #{Float.round(ratio,3)}: #{plausibility}"
      ratio > plausibility_ratio
    end)
  end

  def countup(binary, regex) do
    String.split(binary)
    |> Enum.reduce(Map.new, fn word,acc ->
         if match = Regex.run(regex, word),
             do: Dict.update(acc, hd(match), 1, &(&1+1)), else: acc
       end)
  end
end

path = hd(System.argv)
IO.inspect RC.task(path)


package main

import (
    "fmt"
    "math/big"
)

var (
    one   = new(big.Int).SetUint64(1)
    two   = new(big.Int).SetUint64(2)
    three = new(big.Int).SetUint64(3)
    five  = new(big.Int).SetUint64(5)
    seven = new(big.Int).SetUint64(7)
    ten   = new(big.Int).SetUint64(10)
)

func min(a, b *big.Int) *big.Int {
    if a.Cmp(b) < 0 {
        return a
    }
    return b
}

func humble(n int) []*big.Int {
    h := make([]*big.Int, n)
    h[0] = new(big.Int).Set(one)
    next2, next3 := new(big.Int).Set(two), new(big.Int).Set(three)
    next5, next7 := new(big.Int).Set(five), new(big.Int).Set(seven)
    var i, j, k, l int
    for m := 1; m < len(h); m++ {
        h[m] = new(big.Int).Set(min(next2, min(next3, min(next5, next7))))
        if h[m].Cmp(next2) == 0 {
            i++
            next2.Mul(two, h[i])
        }
        if h[m].Cmp(next3) == 0 {
            j++
            next3.Mul(three, h[j])
        }
        if h[m].Cmp(next5) == 0 {
            k++
            next5.Mul(five, h[k])
        }
        if h[m].Cmp(next7) == 0 {
            l++
            next7.Mul(seven, h[l])
        }
    }
    return h
}

func commatize(n int) string {
    s := fmt.Sprintf("%d", n)
    le := len(s)
    for i := le - 3; i >= 1; i -= 3 {
        s = s[0:i] + "," + s[i:]
    }
    return s
}

func main() {
    const n = 13 * 1e6  // calculate the first 13 million humble numbers, say
    h := humble(n)
    fmt.Println("The first 50 humble numbers are:")
    fmt.Println(h[0:50])

    maxDigits := len(h[len(h)-1].String()) - 1
    counts := make([]int, maxDigits+1)
    var maxUsed int
    digits := 1
    pow10 := new(big.Int).Set(ten)
    for i := 0; i < len(h); i++ {
        for {
            if h[i].Cmp(pow10) >= 0 {
                pow10.Mul(pow10, ten)
                digits++
            } else {
                break
            }
        }
        if digits > maxDigits {
            maxUsed = i
            break
        }
        counts[digits]++
    }
    fmt.Printf("\nOf the first %s humble numbers:\n", commatize(maxUsed))
    for i := 1; i <= maxDigits; i++ {
        s := "s"
        if i == 1 {
            s = ""
        }
        fmt.Printf("%9s have %2d digit%s\n", commatize(counts[i]), i, s)
    }
}


-module(cei).
-export([plaus/0,count/3]).

plaus() ->
    {ok,Words} = file:read_file("unixdict.txt"),
    Swords = string:tokens(erlang:binary_to_list(Words), "\n"),
    EiF = count(Swords,"[^c]ei",0),
    IeF = count(Swords,"[^c]ie",0),
    CeiF = count(Swords,"cei",0),
    CieF = count(Swords,"cie",0),
    if CeiF >= 2 * CieF -> P1= 'is'; true -> P1 = 'is not' end,
    if IeF >= 2 * EiF -> P2 = 'is'; true -> P2 = 'is not' end,
    if P1 == 'is' andalso p2 == 'is' -> P3 ='is'; true -> P3 = 'is not' end,
    io:format("Proposition 1. ~w plausible: ie ~w, ei ~w~n", [P2,IeF,EiF]),
    io:format("Proposition 2. ~w plausible: cei ~w, cie ~w~n", [P1,CeiF,CieF]),
    io:format("The rule ~w plausible~n", [P3]).

count(List,Pattern,Acc) when length(List) == 0 -> Acc;
count(List,Pattern,Acc) ->
    [H|T] = List,
    case re:run(H,Pattern,[global,{capture,none}]) of
        match -> count(T,Pattern, Acc + 1);
        nomatch -> count(T,Pattern, Acc)
    end.


import Data.Set (deleteFindMin, fromList, union)
import Data.List.Split (chunksOf)
import Data.List (group)
import Data.Bool (bool)

--------------------- HUMBLE NUMBERS ----------------------
humbles :: [Integer]
humbles = go $ fromList [1]
  where
    go sofar = x : go (union pruned $ fromList ((x *) <$> [2, 3, 5, 7]))
      where
        (x, pruned) = deleteFindMin sofar

-- humbles = filter (all (< 8) . primeFactors) [1 ..]
-------------------------- TEST ---------------------------
main :: IO ()
main = do
  putStrLn "First 50 Humble numbers:"
  mapM_ (putStrLn . concat) $
    chunksOf 10 $ justifyRight 4 ' ' . show <$> take 50 humbles
  putStrLn "\nCount of humble numbers for each digit length 1-25:"
  mapM_ print $
    take 25 $ ((,) . head <*> length) <$> group (length . show <$> humbles)

------------------------- DISPLAY -------------------------
justifyRight :: Int -> a -> [a] -> [a]
justifyRight n c = (drop . length) <*> (replicate n c ++)


humble=: 4 : 0
 NB. x humble y  generates x humble numbers based on factors y
 result=. , 1
 while. x > # result do.
  a=. , result */ y
  result=. result , <./ a #~ a > {: result
 end.
)


USING: combinators formatting generalizations io.encodings.utf8
io.files kernel literals math prettyprint regexp sequences ;
IN: rosetta-code.i-before-e

: correct ( #correct #incorrect rule-str -- )
    pprint " is correct for %d and incorrect for %d.\n" printf ;

: plausibility ( #correct #incorrect -- str )
    2 * > "plausible" "implausible" ? ;

: output ( #correct #incorrect rule-str -- )
    [ correct ] curry
    [ plausibility "This is %s.\n\n" printf ] 2bi ;

"unixdict.txt" utf8 file-lines ${
    R/ cei/ R/ cie/ R/ [^c]ie/ R/ [^c]ei/
    [ count-matches ]
    [ map-sum       ]
    [ 4 apply-curry ] [email protected]
} cleave

"I before E when not preceded by C"
"E before I when preceded by C" [ output ] [email protected]


!-*- mode: compilation; default-directory: "/tmp/" -*-
!Compilation started at Sat May 18 22:19:19
!
!a=./F && make $a && $a < unixdict.txt
!f95 -Wall -ffree-form F.F -o F
!   ie   ei  cie  cei
!  490  230   24   13
!         [^c]ie plausible
!            cei implausible
! ([^c]ie)|(cei) implausible
!
!Compilation finished at Sat May 18 22:19:19

! test the plausibility of i before e except...
program cia
  implicit none
  character (len=256) :: s
  integer :: ie, ei, cie, cei
  integer :: ios
  data ie, ei, cie, cei/4*0/
  do while (.true.)
    read(5,*,iostat = ios)s
    if (0 .ne. ios) then
      exit
    endif
    call lower_case(s)
    cie = cie + occurrences(s, 'cie')
    cei = cei + occurrences(s, 'cei')
    ie = ie + occurrences(s, 'ie')
    ei = ei + occurrences(s, 'ei')
  enddo
  write(6,'(1x,4(a4,1x))') 'ie','ei','cie','cei'
  write(6,'(1x,4(i4,1x))') ie,ei,cie,cei ! 488 230 24 13
  write(6,'(1x,2(a,1x))') '        [^c]ie',plausibility(ie,ei)
  write(6,'(1x,2(a,1x))') '           cei',plausibility(cei,cie)
  write(6,'(1x,2(a,1x))') '([^c]ie)|(cei)',plausibility(ie+cei,ei+cie)

contains

  subroutine lower_case(s)
    character(len=*), intent(inout) :: s
    integer :: i
    do i=1, len_trim(s)
      s(i:i) = achar(ior(iachar(s(i:i)),32))
    enddo
  end subroutine lower_case

  integer function occurrences(a,b)
    character(len=*), intent(in) :: a, b
    integer :: i, j, n
    n = 0
    i = 0
    j = index(a, b)
    do while (0 .lt. j)
      n = n+1
      i = i+len(b)+j-1
      j = index(a(i:), b)
    end do
    occurrences = n
  end function occurrences

  character*(32) function plausibility(da, nyet)
    integer, intent(in) :: da, nyet
    !write(0,*)da,nyet
    if (nyet*2 .lt. da) then
      plausibility = 'plausible'
    else
      plausibility = 'implausible'
    endif
  end function plausibility
end program cia


import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class HumbleNumbers {

    public static void main(String[] args) {
        System.out.println("First 50 humble numbers:");
        System.out.println(Arrays.toString(humble(50)));
        Map<Integer,Integer> lengthCountMap = new HashMap<>();
        BigInteger[] seq = humble(1_000_000);
        for ( int i = 0 ; i < seq.length ; i++ ) {
            BigInteger humbleNumber = seq[i];
            int len = humbleNumber.toString().length();
            lengthCountMap.merge(len, 1, (v1, v2) -> v1 + v2);
        }
        List<Integer> sorted = new ArrayList<>(lengthCountMap.keySet());
        Collections.sort(sorted);
        System.out.printf("Length  Count%n");
        for ( Integer len : sorted ) {
            System.out.printf("    %2s  %5s%n", len, lengthCountMap.get(len));
        }
    }

    private static BigInteger[] humble(int n) {
        BigInteger two = BigInteger.valueOf(2);
        BigInteger twoTest = two;
        BigInteger three = BigInteger.valueOf(3);
        BigInteger threeTest = three;
        BigInteger five = BigInteger.valueOf(5);
        BigInteger fiveTest = five;
        BigInteger seven = BigInteger.valueOf(7);
        BigInteger sevenTest = seven;
        BigInteger[] results = new BigInteger[n];
        results[0] = BigInteger.ONE;
        int twoIndex = 0, threeIndex = 0, fiveIndex = 0, sevenIndex = 0;
        for ( int index = 1 ; index < n ; index++ ) {
            results[index] = twoTest.min(threeTest).min(fiveTest).min(sevenTest);
            if ( results[index].compareTo(twoTest) == 0 ) {
                twoIndex++;
                twoTest = two.multiply(results[twoIndex]);
            }
            if (results[index].compareTo(threeTest) == 0 ) {
                threeIndex++;
                threeTest = three.multiply(results[threeIndex]);
            }
            if (results[index].compareTo(fiveTest) == 0 ) {
                fiveIndex++;
                fiveTest = five.multiply(results[fiveIndex]);
            }
            if (results[index].compareTo(sevenTest) == 0 ) {
                sevenIndex++;
                sevenTest = seven.multiply(results[sevenIndex]);
            }
        }
        return results;
    }

}


Function getfile(file As String) As String
    Dim As Integer F = Freefile
    Dim As String text,intext
    Open file For Input As #F
    Line Input #F,text
    While Not Eof(F)
        Line Input #F,intext
        text=text+Chr(10)+intext
    Wend
    close #F
    Return text
End Function

Function TALLY(instring As String,PartString As String) As Integer
        Dim count As Integer
        var lens2=Len(PartString)
        Dim As String s=instring
        Dim As Integer position=Instr(s,PartString)
        If position=0 Then Return 0
        While position>0
            count=count+1
            position=Instr(position+Lens2,s,PartString)
        Wend
        Function=count
    End Function

Dim As String myfile="unixdict.txt"

Dim As String wordlist= getfile(myfile)
wordlist=lcase(wordlist)

print
print "The number of words in unixdict.txt  ",TALLY(wordlist,chr(10))+1
print
dim as integer cei=TALLY(wordlist,"cei")
print "Instances of cei",cei
dim as integer cie=TALLY(wordlist,"cie")
print "Instances of cie",cie
print
dim as integer ei=TALLY(wordlist,"ei")
print "Instances of *ei, where * is not c",ei-cei
dim as integer ie=TALLY(wordlist,"ie")
print "Instances of *ie, where * is not c",ie-cie
print
print "Conclusion:"
print "ie is plausible when not preceeded by c, the ratio is ";(ie-cie)/(ei-cei)
print "ei is not plausible when preceeded by c, the ratio is ";cei/cie
print "So, the idea is not plausible."

Sleep


include "NSLog.incl"

#plist NSAppTransportSecurity @{NSAllowsArbitraryLoads:YES}

void local fn CheckWord( wrd as CFStringRef, txt as CFStringRef, c as ^long, x as ^long )
  CFRange range = fn StringRangeOfString( wrd, txt )
  while ( range.location != NSNotFound )
    if ( range.location > 0 )
      select ( fn StringCharacterAtIndex( wrd, range.location-1 ) )
        case _"c"
          *c += 1
        case else
          *x += 1
      end select
    else
      *x += 1
    end if
    range.location++
    range.length = len(wrd) - range.location
    range = fn StringRangeOfStringWithOptionsInRange( wrd, txt, 0, range )
  wend
end fn

void local fn Doit
  CFURLRef    url    = fn URLWithString( @"http://wiki.puzzlers.org/pub/wordlists/unixdict.txt" )
  CFStringRef string = fn StringWithContentsOfURL( url, NSUTF8StringEncoding, NULL )
  CFArrayRef  words  = fn StringComponentsSeparatedByCharactersInSet( string, fn CharacterSetNewlineSet )
  long        cei    = 0, cie = 0, xei = 0, xie = 0
  CFStringRef wrd, result

  for wrd in words
    fn CheckWord( wrd, @"ei", @cei, @xei )
    fn CheckWord( wrd, @"ie", @cie, @xie )
  next

  NSLog(@"cei: %ld",cei)
  NSLog(@"cie: %ld",cie)
  NSLog(@"xei: %ld",xei)
  NSLog(@"xie: %ld",xie)

  if 2 * xie <= cie then result = @"not plausible" else result = @"plausible"
  NSLog( @"\nI before E when not preceded by C: %@.\n¬
  There are %ld examples and %ld counter-examples for a ratio of %f.\n", ¬
  result, xie, xei, ( ( (float)xie - (float)cie ) / ( (float)xei - (float)cei ) ) )

  if 2 * cei <= xei then result = @"not plausible" else result = @"plausible"
  NSLog( @"E before I when preceded by C: %@.\n¬
  There are %ld examples and %ld counter-examples for a ratio of %f.\n", ¬
  result, cei, cie, ( (float)cei / (float)cie ) )
end fn

fn DoIt

HandleEvents