#include <stdio.h>
#include <complex.h>
#include <math.h>

/* Testing macros */
#define FMTSPEC(arg) _Generic((arg), \
    float: "%f", double: "%f", \
    long double: "%Lf", unsigned int: "%u", \
    unsigned long: "%lu", unsigned long long: "%llu", \
    int: "%d", long: "%ld", long long: "%lld", \
    default: "(invalid type (%p)")

#define CMPPARTS(x, y) ((long double complex)((long double)(x) + \
            I * (long double)(y)))

#define TEST_CMPL(i, j)\
    printf(FMTSPEC(i), i), printf(" + "), printf(FMTSPEC(j), j), \
    printf("i = %s\n", (isint(CMPPARTS(i, j)) ? "true" : "false"))

#define TEST_REAL(i)\
    printf(FMTSPEC(i), i), printf(" = %s\n", (isint(i) ? "true" : "false"))

/* Main code */
static inline int isint(long double complex n)
{
    return cimagl(n) == 0 && nearbyintl(creall(n)) == creall(n);
}

int main(void)
{
    TEST_REAL(0);
    TEST_REAL(-0);
    TEST_REAL(-2);
    TEST_REAL(-2.00000000000001);
    TEST_REAL(5);
    TEST_REAL(7.3333333333333);
    TEST_REAL(3.141592653589);
    TEST_REAL(-9.223372036854776e18);
    TEST_REAL(5e-324);
    TEST_REAL(NAN);
    TEST_CMPL(6, 0);
    TEST_CMPL(0, 1);
    TEST_CMPL(0, 0);
    TEST_CMPL(3.4, 0);

    /* Demonstrating that we can use the same function for complex values
     * constructed in the standard way */
    double complex test1 = 5 + 0*I,
                   test2 = 3.4f,
                   test3 = 3,
                   test4 = 0 + 1.2*I;

    printf("Test 1 (5+i) = %s\n", isint(test1) ? "true" : "false");
    printf("Test 2 (3.4+0i) = %s\n", isint(test2) ? "true" : "false");
    printf("Test 3 (3+0i) = %s\n", isint(test3) ? "true" : "false");
    printf("Test 4 (0+1.2i) = %s\n", isint(test4) ? "true" : "false");
}


namespace Test_integerness
{
	class Program
	{
		public static void Main(string[] args)
		{
			Console.Clear();
			Console.WriteLine();
			Console.WriteLine(" ***************************************************");
			Console.WriteLine(" *                                                 *");
			Console.WriteLine(" *              Integerness test                   *");
			Console.WriteLine(" *                                                 *");
			Console.WriteLine(" ***************************************************");
			Console.WriteLine();

			ConsoleKeyInfo key = new ConsoleKeyInfo('Y',ConsoleKey.Y,true,true,true);

			while(key.Key == ConsoleKey.Y)
			{
				// Get number value from keyboard
				Console.Write(" Enter number value : ");

				string LINE = Console.ReadLine();

				// Get tolerance value from keyboard
				Console.Write(" Enter tolerance value : ");

				double TOLERANCE = double.Parse(Console.ReadLine());

				// Resolve entered number format and set NUMBER value
				double NUMBER = 0;

				string [] N;

				// Real number value
				if(!double.TryParse(LINE, out NUMBER))
				{
					// Rational number value
					if(LINE.Contains("/"))
					{
						N = LINE.Split('/');

						NUMBER = double.Parse(N[0]) / double.Parse(N[1]);
					}
					// Inf value
					else if(LINE.ToUpper().Contains("INF"))
					{
						NUMBER = double.PositiveInfinity;
					}
					// Complex value
					else if(LINE.ToUpper().Contains("I"))
					{
						// Delete letter i
						LINE = LINE.ToUpper().Replace("I","");

						string r = string.Empty; // real part
						string i = string.Empty; // imaginary part

						int s = 1; // sign offset

						// Get sign
						if(LINE[0]=='+' || LINE[0]=='-')
						{
							r+=LINE[0].ToString();
							LINE = LINE.Remove(0,1);
							s--;
						}
						// Get real part
						foreach (char element in LINE)
						{
							if(element!='+' && element!='-')
								r+=element.ToString();
							else
								break;
						}
						// get imaginary part
						i = LINE.Substring(LINE.Length-(r.Length+s));

						NUMBER = double.Parse(i);
						if(NUMBER==0)
							NUMBER = double.Parse(r);
						else
							NUMBER = double.NaN;

					}
					// NaN value
					else
						NUMBER = double.NaN;
				}

				// Test
				bool IS_INTEGER = false;
				bool IS_INTEGER_T = false;

				if(double.IsNaN(NUMBER))
					IS_INTEGER=false;

				else if(Math.Round(NUMBER,0).ToString() == NUMBER.ToString())
					IS_INTEGER = true;

				else if((decimal)TOLERANCE >= (decimal)Math.Abs( (decimal)Math.Round(NUMBER,0) - (decimal)NUMBER ))
					IS_INTEGER_T = true;

				if(IS_INTEGER)
					Console.WriteLine(" Is exact integer " + IS_INTEGER);

				else
				{
					Console.WriteLine( " Is exact integer " + IS_INTEGER );
					Console.WriteLine( " Is integer with tolerance " + IS_INTEGER_T );
				}

				Console.WriteLine();
				Console.Write(" Another test < Y /N > . . . ");
				key  = Console.ReadKey(true);
				Console.WriteLine();
				Console.WriteLine();
			}

		}

	}
}


#lang racket
(module+ test (require tests/eli-tester))
(module+ test
  (test
   (map char->sms-digit (string->list "ABCDEFGHIJKLMNOPQRSTUVWXYZ."))
   => (list 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6 7 7 7 7 8 8 8 9 9 9 9 #f)))

(define char->sms-digit
  (match-lambda
    [(? char-lower-case? (app char-upcase C)) (char->sms-digit C)]
    ;; Digits, too, can be entered on a text pad!
    [(? char-numeric? (app char->integer c)) (- c (char->integer #\0))]
    [(or #\A #\B #\C) 2]
    [(or #\D #\E #\F) 3]
    [(or #\G #\H #\I) 4]
    [(or #\J #\K #\L) 5]
    [(or #\M #\N #\O) 6]
    [(or #\P #\Q #\R #\S) 7]
    [(or #\T #\U #\V) 8]
    [(or #\W #\X #\Y #\Z) 9]
    [_ #f]))

(module+ test
  (test
   (word->textonym "criticisms") => 2748424767
   (word->textonym "Briticisms") => 2748424767
   (= (word->textonym "Briticisms") (word->textonym "criticisms"))))

(define (word->textonym w)
  (for/fold ((n 0)) ((s (sequence-map char->sms-digit (in-string w))) #:final (not s))
    (and s (+ (* n 10) s))))

(module+ test
  (test
   ((cons-uniquely 'a) null) => '(a)
   ((cons-uniquely 'a) '(b)) => '(a b)
   ((cons-uniquely 'a) '(a b c)) => '(a b c)))

(define ((cons-uniquely a) d)
  (if (member a d) d (cons a d)))

(module+ test
  (test
   (with-input-from-string "criticisms" port->textonym#) =>
   (values 1 (hash 2748424767 '("criticisms")))
   (with-input-from-string "criticisms\nBriticisms" port->textonym#) =>
   (values 2 (hash 2748424767 '("Briticisms" "criticisms")))
   (with-input-from-string "oh-no!-dashes" port->textonym#) =>
   (values 0 (hash))))

(define (port->textonym#)
  (for/fold
   ((n 0) (t# (hash)))
   ((w (in-port read-line)))
    (define s (word->textonym w))
    (if s
        (values (+ n 1) (hash-update t# s (cons-uniquely w) null))
        (values n t#))))

(define (report-on-file f-name)
  (define-values (n-words textonym#) (with-input-from-file f-name port->textonym#))

  (define n-textonyms (for/sum ((v (in-hash-values textonym#)) #:when (> (length v) 1)) 1))

  (printf "--- report on ~s ends ---~%" f-name)
  (printf
   #<<EOS
There are ~a words in ~s which can be represented by the digit key mapping.
They require ~a digit combinations to represent them.
~a digit combinations represent Textonyms.

EOS
   n-words f-name (hash-count textonym#) n-textonyms)

  ;; Show all the 6+ textonyms
  (newline)
  (for (((k v) (in-hash textonym#)) #:when (>= (length v) 6)) (printf "~a -> ~s~%" k v))
  (printf "--- report on ~s ends ---~%" f-name))

(module+ main
  (report-on-file "data/unixdict.txt"))


my $src = 'unixdict.txt';

my @words = slurp($src).lines.grep(/ ^ <alpha>+ $ /);

my @dials = @words.classify: {
    .trans('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
        => '2223334445556667777888999922233344455566677778889999');
}

my @textonyms = @dials.grep(*.value > 1);

say qq:to 'END';
    There are {[email protected]words} words in $src which can be represented by the digit key mapping.
    They require {+@dials} digit combinations to represent them.
    {+@textonyms} digit combinations represent Textonyms.
    END

say "Top 5 in ambiguity:";
say "    ",$_ for @textonyms.sort(-*.value)[^5];

say "\nTop 5 in length:";
say "    ",$_ for @textonyms.sort(-*.key.chars)[^5];


/*REXX program counts and displays the number of textonyms that are in a dictionary file*/
parse arg iFID .                                 /*obtain optional fileID from the C.L. */
if iFID=='' | iFID=="," then iFID='UNIXDICT.TXT' /*Not specified?  Then use the default.*/
@.= 0                                            /*the placeholder of digit combinations*/
!.=;       $.=                                   /*sparse array of textonyms;  words.   */
alphabet= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'           /*the supported alphabet to be used.   */
digitKey=  22233344455566677778889999            /*translated alphabet to digit keys.   */
digKey= 0;                 #word= 0              /*number digit combinations; word count*/
ills= 0 ;    dups= 0;    longest= 0;   mostus= 0 /*illegals; duplicated words; longest..*/
first=. ;    last= .;       long= 0;   most=   0 /*first, last, longest, most counts.   */
call linein  iFID, 1, 0                          /*point to the first char in dictionary*/
#= 0                                             /*number of textonyms in file (so far).*/

  do while  lines(iFID)\==0;     x= linein(iFID) /*keep reading the file until exhausted*/
  y= x;     upper x                              /*save a copy of  X;    uppercase  X.  */
  if \datatype(x, 'U')  then do;  ills= ills + 1;  iterate;  end     /*Not legal?  Skip.*/
  if $.x==.             then do;  dups= dups + 1;  iterate;  end     /*Duplicate?  Skip.*/
  $.x= .                                         /*indicate that it's a righteous word. */
  #word= #word + 1                               /*bump the word count  (for the file). */
  z= translate(x, digitKey, alphabet)            /*build a translated digit key word.   */
  @.z= @.z + 1                                   /*flag that the digit key word exists. */
  !.z= !.z  y;        _= words(!.z)              /*build list of equivalent digit key(s)*/

  if _>most  then do; mostus= z;  most= _;  end  /*remember the  "mostus"  digit keys.  */

  if @.z==2  then do; #= # + 1                   /*bump the count of the  textonyms.    */
                      if first==.   then first=z /*the first textonym found.            */
                      last= z                    /* "   last     "      "               */
                      _= length(!.z)             /*the length (# chars) of the digit key*/
                      if _>longest  then long= z /*is this the  longest  textonym ?     */
                      longest= max(_, longest)   /*now, use this length as a target/goal*/
                  end                            /* [↑]  discretionary  (extra credit). */

  if @.z==1  then digKey= digKey + 1             /*bump the count of digit key words.   */
  end   /*while*/

@dict= 'in the dictionary file'                  /*literal used for some displayed text.*/
L= length(commas(max(#word,ills,dups,digKey,#))) /*find length of max # being displayed.*/
say 'The dictionary file being used is: '   iFID
say
                call tell #word,  'words'                                           @dict,
                                  "which can be represented by digit key mapping"
if ills>0  then call tell ills,   'word's(ills)  "that contain illegal characters"  @dict
if dups>0  then call tell dups,   'duplicate word's(dups)  "detected"               @dict
                call tell digKey, 'combination's(digKey)   "required to represent them"
                call tell      #, 'digit combination's(#)  "that can represent Textonyms"
say
if first \== .  then say '    first digit key='   !.first
if  last \== .  then say '     last digit key='   !.last
if  long \== 0  then say '  longest digit key='   !.long
if  most \== 0  then say ' numerous digit key='   !.mostus   " ("most   'words)'
exit #                                           /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
commas: parse arg _;  do jc=length(_)-3  to 1  by -3; _=insert(',', _, jc); end;  return _
tell:   arg ##; say 'There are ' right(commas(##), L)' ' arg(2).; return   /*commatize #*/
s:      if arg(1)==1  then return '';      return "s"             /*a simple pluralizer.*/


#include <complex>
#include <math.h>
#include <iostream>

template<class Type>
struct Precision
{
public:
	static Type GetEps()
	{
		return eps;
	}

	static void SetEps(Type e)
	{
		eps = e;
	}

private:
	static Type eps;
};

template<class Type> Type Precision<Type>::eps = static_cast<Type>(1E-7);

template<class DigType>
bool IsDoubleEqual(DigType d1, DigType d2)
{
	return (fabs(d1 - d2) < Precision<DigType>::GetEps());
}

template<class DigType>
DigType IntegerPart(DigType value)
{
	return (value > 0) ? floor(value) : ceil(value);
}

template<class DigType>
DigType FractionPart(DigType value)
{
	return fabs(IntegerPart<DigType>(value) - value);
}

template<class Type>
bool IsInteger(const Type& value)
{
	return false;
}

#define GEN_CHECK_INTEGER(type)			\
template<>					\
bool IsInteger<type>(const type& value)         \
{						\
	return true;				\
}

#define GEN_CHECK_CMPL_INTEGER(type)					\
template<>								\
bool IsInteger<std::complex<type> >(const std::complex<type>& value)	\
{									\
	type zero = type();						\
	return value.imag() == zero;					\
}

#define GEN_CHECK_REAL(type)						\
template<>								\
bool IsInteger<type>(const type& value)					\
{									\
	type zero = type();						\
	return IsDoubleEqual<type>(FractionPart<type>(value), zero);	\
}

#define GEN_CHECK_CMPL_REAL(type)					\
template<>								\
bool IsInteger<std::complex<type> >(const std::complex<type>& value)	\
{									\
	type zero = type();						\
	return IsDoubleEqual<type>(value.imag(), zero);			\
}

#define GEN_INTEGER(type)		\
	GEN_CHECK_INTEGER(type)		\
	GEN_CHECK_CMPL_INTEGER(type)

#define GEN_REAL(type)			\
	GEN_CHECK_REAL(type)		\
	GEN_CHECK_CMPL_REAL(type)

GEN_INTEGER(char)
GEN_INTEGER(unsigned char)
GEN_INTEGER(short)
GEN_INTEGER(unsigned short)
GEN_INTEGER(int)
GEN_INTEGER(unsigned int)
GEN_INTEGER(long)
GEN_INTEGER(unsigned long)
GEN_INTEGER(long long)
GEN_INTEGER(unsigned long long)

GEN_REAL(float)
GEN_REAL(double)
GEN_REAL(long double)

template<class Type>
inline void TestValue(const Type& value)
{
	std::cout << "Value: " << value << " of type: " << typeid(Type).name() << " is integer - " << std::boolalpha << IsInteger(value) << std::endl;
}

int main()
{
	char c = -100;
	unsigned char uc = 200;
	short s = c;
	unsigned short us = uc;
	int i = s;
	unsigned int ui = us;
	long long ll = i;
	unsigned long long ull = ui;

	std::complex<unsigned int> ci1(2, 0);
	std::complex<int> ci2(2, 4);
	std::complex<int> ci3(-2, 4);
	std::complex<unsigned short> cs1(2, 0);
	std::complex<short> cs2(2, 4);
	std::complex<short> cs3(-2, 4);

	std::complex<double> cd1(2, 0);
	std::complex<float> cf1(2, 4);
	std::complex<double> cd2(-2, 4);

	float f1 = 1.0;
	float f2 = -2.0;
	float f3 = -2.4f;
	float f4 = 1.23e-5f;
	float f5 = 1.23e-10f;
	double d1 = f5;

	TestValue(c);
	TestValue(uc);
	TestValue(s);
	TestValue(us);
	TestValue(i);
	TestValue(ui);
	TestValue(ll);
	TestValue(ull);

	TestValue(ci1);
	TestValue(ci2);
	TestValue(ci3);
	TestValue(cs1);
	TestValue(cs2);
	TestValue(cs3);

	TestValue(cd1);
	TestValue(cd2);
	TestValue(cf1);

	TestValue(f1);
	TestValue(f2);
	TestValue(f3);
	TestValue(f4);
	TestValue(f5);
	std::cout << "Set float precision: 1e-15f\n";
	Precision<float>::SetEps(1e-15f);
	TestValue(f5);
	TestValue(d1);
	return 0;
}


CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
NUMS  = "22233344455566677778889999" * 2
dict  = "unixdict.txt"

textonyms = File.open(dict){|f| f.map(&:chomp).group_by {|word| word.tr(CHARS, NUMS) } }

puts "There are #{File.readlines(dict).size} words in #{dict} which can be represented by the digit key mapping.
They require #{textonyms.size} digit combinations to represent them.
#{textonyms.count{|_,v| v.size > 1}} digit combinations represent Textonyms."

puts "\n25287876746242: #{textonyms["25287876746242"].join(", ")}"


use std::collections::HashMap;
use std::fs::File;
use std::io::{self, BufRead};

fn text_char(ch: char) -> Option<char> {
    match ch {
        'a' | 'b' | 'c' => Some('2'),
        'd' | 'e' | 'f' => Some('3'),
        'g' | 'h' | 'i' => Some('4'),
        'j' | 'k' | 'l' => Some('5'),
        'm' | 'n' | 'o' => Some('6'),
        'p' | 'q' | 'r' | 's' => Some('7'),
        't' | 'u' | 'v' => Some('8'),
        'w' | 'x' | 'y' | 'z' => Some('9'),
        _ => None,
    }
}

fn text_string(s: &str) -> Option<String> {
    let mut text = String::with_capacity(s.len());
    for c in s.chars() {
        if let Some(t) = text_char(c) {
            text.push(t);
        } else {
            return None;
        }
    }
    Some(text)
}

fn print_top_words(textonyms: &Vec<(&String, &Vec<String>)>, top: usize) {
    for (text, words) in textonyms.iter().take(top) {
        println!("{} = {}", text, words.join(", "));
    }
}

fn find_textonyms(filename: &str) -> std::io::Result<()> {
    let file = File::open(filename)?;
    let mut table = HashMap::new();
    let mut count = 0;

    for line in io::BufReader::new(file).lines() {
        let mut word = line?;
        word.make_ascii_lowercase();
        if let Some(text) = text_string(&word) {
            let words = table.entry(text).or_insert(Vec::new());
            words.push(word);
            count += 1;
        }
    }

    let mut textonyms: Vec<(&String, &Vec<String>)> =
        table.iter().filter(|x| x.1.len() > 1).collect();

    println!(
        "There are {} words in '{}' which can be represented by the digit key mapping.",
        count, filename
    );
    println!(
        "They require {} digit combinations to represent them.",
        table.len()
    );
    println!(
        "{} digit combinations represent Textonyms.",
        textonyms.len()
    );

    let top = std::cmp::min(5, textonyms.len());
    textonyms.sort_by_key(|x| (std::cmp::Reverse(x.1.len()), x.0));
    println!("\nTop {} by number of words:", top);
    print_top_words(&textonyms, top);

    textonyms.sort_by_key(|x| (std::cmp::Reverse(x.0.len()), x.0));
    println!("\nTop {} by length:", top);
    print_top_words(&textonyms, top);

    Ok(())
}

fn main() {
    let args: Vec<String> = std::env::args().collect();
    if args.len() != 2 {
        eprintln!("usage: {} word-list", args[0]);
        std::process::exit(1);
    }
    match find_textonyms(&args[1]) {
        Ok(()) => {}
        Err(error) => eprintln!("{}: {}", args[1], error),
    }
}


var words = ARGF.grep(/^[[:alpha:]]+\z/);

var dials = words.group_by {
    .tr('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
        '2223334445556667777888999922233344455566677778889999');
}

var textonyms = dials.grep_v { .len > 1 };

say <<-END;
    There are #{words.len} words which can be represented by the digit key mapping.
    They require #{dials.len} digit combinations to represent them.
    #{textonyms.len} digit combinations represent Textonyms.
    END

say "Top 5 in ambiguity:";
say textonyms.sort_by { |_,v| -v.len }.first(5).join("\n");

say "\nTop 5 in length:";
say textonyms.sort_by { |k,_| -k.len }.first(5).join("\n");


IDENTIFICATION DIVISION.
PROGRAM-ID. INTEGERNESS-PROGRAM.
DATA DIVISION.
WORKING-STORAGE SECTION.
01  INTEGERS-OR-ARE-THEY.
    05 POSSIBLE-INTEGER PIC S9(9)V9(9).
    05 DEFINITE-INTEGER PIC S9(9).
01  COMPLEX-NUMBER.
    05 REAL-PART        PIC S9(9)V9(9).
    05 IMAGINARY-PART   PIC S9(9)V9(9).
PROCEDURE DIVISION.
TEST-PARAGRAPH.
    MOVE ZERO TO IMAGINARY-PART.
    DIVIDE -28 BY 7 GIVING POSSIBLE-INTEGER.
    PERFORM INTEGER-PARAGRAPH.
    DIVIDE 28 BY 18 GIVING POSSIBLE-INTEGER.
    PERFORM INTEGER-PARAGRAPH.
    DIVIDE 3 BY 10000000000 GIVING POSSIBLE-INTEGER.
    PERFORM INTEGER-PARAGRAPH.
TEST-COMPLEX-PARAGRAPH.
    MOVE ZERO TO REAL-PART.
    MOVE 1 TO IMAGINARY-PART.
    MOVE REAL-PART TO POSSIBLE-INTEGER.
    PERFORM INTEGER-PARAGRAPH.
    STOP RUN.
INTEGER-PARAGRAPH.
    IF IMAGINARY-PART IS EQUAL TO ZERO THEN PERFORM REAL-PARAGRAPH,
    ELSE PERFORM COMPLEX-PARAGRAPH.
REAL-PARAGRAPH.
    MOVE POSSIBLE-INTEGER TO DEFINITE-INTEGER.
    IF DEFINITE-INTEGER IS EQUAL TO POSSIBLE-INTEGER
    THEN DISPLAY POSSIBLE-INTEGER ' IS AN INTEGER.',
    ELSE DISPLAY POSSIBLE-INTEGER ' IS NOT AN INTEGER.'.
COMPLEX-PARAGRAPH.
    DISPLAY REAL-PART '+' IMAGINARY-PART 'i IS NOT AN INTEGER.'.


import std.complex;
import std.math;
import std.meta;
import std.stdio;
import std.traits;

void main() {
    print(25.000000);
    print(24.999999);
    print(24.999999, 0.00001);
    print(25.000100);
    print(-2.1e120);
    print(-5e-2);
    print(real.nan);
    print(real.infinity);
    print(5.0+0.0i);
    print(5-5i);
}

void print(T)(T v, real tol = 0.0) {
    writefln("Is %0.10s an integer? %s", v, isInteger(v, tol));
}

/// Test for plain integers
bool isInteger(T)(T v)
if (isIntegral!T) {
    return true;
}

unittest {
    assert(isInteger(5));
    assert(isInteger(-5));

    assert(isInteger(2L));
    assert(isInteger(-2L));
}

/// Test for floating point
bool isInteger(T)(T v, real tol = 0.0)
if (isFloatingPoint!T) {
    return (v - floor(v)) <= tol || (ceil(v) - v) <= tol;
}

unittest {
    assert(isInteger(25.000000));

    assert(!isInteger(24.999999));
    assert(isInteger(24.999999, 0.00001));
}

/// Test for complex numbers
bool isInteger(T)(Complex!T v, real tol = 0.0) {
    return isInteger(v.re, tol) && abs(v.im) <= tol;
}

unittest {
    assert(isInteger(complex(1.0)));
    assert(!isInteger(complex(1.0, 0.0001)));

    assert(isInteger(complex(1.0, 0.00009), 0.0001));
}

/// Test for built-in complex types
bool isInteger(T)(T v, real tol = 0.0)
if (staticIndexOf!(Unqual!T, AliasSeq!(cfloat, cdouble, creal)) >= 0) {
    return isInteger(v.re, tol) && abs(v.im) <= tol;
}

unittest {
    assert(isInteger(1.0 + 0.0i));
    assert(!isInteger(1.0 + 0.0001i));

    assert(isInteger(1.0 + 0.00009i, 0.0001));
}

/// Test for built-in imaginary types
bool isInteger(T)(T v, real tol = 0.0)
if (staticIndexOf!(Unqual!T, AliasSeq!(ifloat, idouble, ireal)) >= 0) {
    return abs(v) <= tol;
}

unittest {
    assert(isInteger(0.0i));
    assert(!isInteger(0.0001i));

    assert(isInteger(0.00009i, 0.0001));
}


import Foundation

func textCharacter(_ ch: Character) -> Character? {
    switch (ch) {
    case "a", "b", "c":
        return "2"
    case "d", "e", "f":
        return "3"
    case "g", "h", "i":
        return "4"
    case "j", "k", "l":
        return "5"
    case "m", "n", "o":
        return "6"
    case "p", "q", "r", "s":
        return "7"
    case "t", "u", "v":
        return "8"
    case "w", "x", "y", "z":
        return "9"
    default:
        return nil
    }
}

func textString(_ string: String) -> String? {
    var result = String()
    result.reserveCapacity(string.count)
    for ch in string {
        if let tch = textCharacter(ch) {
            result.append(tch)
        } else {
            return nil
        }
    }
    return result
}

func compareByWordCount(pair1: (key: String, value: [String]),
                        pair2: (key: String, value: [String])) -> Bool {
    if pair1.value.count == pair2.value.count {
        return pair1.key < pair2.key
    }
    return pair1.value.count > pair2.value.count
}

func compareByTextLength(pair1: (key: String, value: [String]),
                         pair2: (key: String, value: [String])) -> Bool {
    if pair1.key.count == pair2.key.count {
        return pair1.key < pair2.key
    }
    return pair1.key.count > pair2.key.count
}

func findTextonyms(_ path: String) throws {
    var dict = Dictionary<String, [String]>()
    let contents = try String(contentsOfFile: path, encoding: String.Encoding.ascii)
    var count = 0
    for line in contents.components(separatedBy: "\n") {
        if line.isEmpty {
            continue
        }
        let word = line.lowercased()
        if let text = textString(word) {
            dict[text, default: []].append(word)
            count += 1
        }
    }
    var textonyms = Array(dict.filter{$0.1.count > 1})
    print("There are \(count) words in '\(path)' which can be represented by the digit key mapping.")
    print("They require \(dict.count) digit combinations to represent them.")
    print("\(textonyms.count) digit combinations represent Textonyms.")

    let top = min(5, textonyms.count)
    print("\nTop \(top) by number of words:")
    textonyms.sort(by: compareByWordCount)
    for (text, words) in textonyms.prefix(top) {
        print("\(text) = \(words.joined(separator: ", "))")
    }

    print("\nTop \(top) by length:")
    textonyms.sort(by: compareByTextLength)
    for (text, words) in textonyms.prefix(top) {
        print("\(text) = \(words.joined(separator: ", "))")
    }
}

do {
    try findTextonyms("unixdict.txt")
} catch {
    print(error.localizedDescription)
}


set keymap {
    2 -> ABC
    3 -> DEF
    4 -> GHI
    5 -> JKL
    6 -> MNO
    7 -> PQRS
    8 -> TUV
    9 -> WXYZ
}

set url http://www.puzzlers.org/pub/wordlists/unixdict.txt

set report {
There are %1$s words in %2$s which can be represented by the digit key mapping.
They require %3$s digit combinations to represent them.
%4$s digit combinations represent Textonyms.

A %5$s-letter textonym which has %6$s combinations is %7$s:

  %8$s
}

package require http
proc geturl {url} {
    try {
        set tok [http::geturl $url]
        return [http::data $tok]
    } finally {
        http::cleanup $tok
    }
}

proc main {keymap url} {
    foreach {digit -> letters} $keymap {
        foreach l [split $letters ""] {
            dict set strmap $l $digit
        }
    }
    set doc [geturl $url]
    foreach word [split $doc \n] {
        if {![string is alpha -strict $word]} continue
        dict lappend words [string map $strmap [string toupper $word]] $word
    }

    set ncombos [dict size $words]
    set nwords 0
    set ntextos 0
    set nmax 0
    set dmax ""
    dict for {d ws} $words {
        puts [list $d $ws]
        set n [llength $ws]
        incr nwords $n
        if {$n > 1} {
            incr ntextos $n
        }
        if {$n >= $nmax && [string length $d] > [string length $dmax]} {
            set nmax $n
            set dmax $d
        }
    }
    set maxwords [dict get $words $dmax]
    set lenmax [llength $maxwords]
    format $::report $nwords $url $ncombos $ntextos $lenmax $nmax $dmax $maxwords
}

puts [main $keymap $url]


defmodule Test do
  def integer?(n) when n == trunc(n), do: true
  def integer?(_), do: false
end

Enum.each([2, 2.0, 2.5, 2.000000000000001, 1.23e300, 1.0e-300, "123", '123', :"123"], fn n ->
  IO.puts "#{inspect n} is integer?: #{Test.integer?(n)}"
end)


USING: formatting io kernel math math.functions sequences ;
IN: rosetta-code.test-integerness

GENERIC: integral? ( n -- ? )

M: real integral? [ ] [ >integer ] bi number= ;
M: complex integral? >rect [ integral? ] [ 0 number= ] bi* and ;

GENERIC# fuzzy-int? 1 ( n tolerance -- ? )

M: real fuzzy-int? [ dup round - abs ] dip <= ;
M: complex fuzzy-int? [ >rect ] dip swapd fuzzy-int? swap 0
    number= and ;

{
    25/1
    50+2/3
    34/73
    312459210312903/129381293812491284512951
    25.000000
    24.999999
    25.000100
    -2.1e120
    -5e-2
    0/0. ! NaN
    1/0. ! Infinity
    C{ 5.0 0.0 }
    C{ 5 -5 }
    C{ 5 0 }
}
"Number" "Exact int?" "Fuzzy int? (tolerance=0.00001)"
"%-41s %-11s %s\n" printf
[
   [ ] [ integral? ] [ 0.00001 fuzzy-int? ] tri
   "%-41u %-11u %u\n" printf
] each


      MODULE ZERMELO	!Approach the foundations of mathematics.
       CONTAINS
        LOGICAL FUNCTION ISINTEGRAL(X)	!A whole number?
         REAL*8 X	!Alas, this is not really a REAL number.
         INTEGER*8 N	!Largest available.
          IF (ISNAN(X)) THEN	!Avoid some sillyness.
            ISINTEGRAL = .FALSE.	!And possible error messages.
          ELSE			!But now it is safe to try.
            N = KIDINT(X)		!This one truncates.
            ISINTEGRAL = N .EQ. X	!Any difference?
          END IF		!A floating-point number may overflow an integer.
        END FUNCTION ISINTEGRAL	!And even if integral, it will not seem so.

        LOGICAL FUNCTION ISINTEGRALZ(Z)	!For complex numbers, two tests.
         DOUBLE COMPLEX Z	!Still not really REAL, though.
          ISINTEGRALZ = ISINTEGRAL(DBLE(Z)) .AND. ISINTEGRAL(DIMAG(Z))	!Separate the parts.
        END FUNCTION ISINTEGRALZ!No INTEGER COMPLEX type is offered.
      END MODULE ZERMELO	!Much more mathematics lie elsewhere.

      PROGRAM TEST
      USE ZERMELO
      DOUBLE COMPLEX Z

      WRITE (6,*) "See if some numbers are integral..."
      WRITE (6,*) ISINTEGRAL(666D0),666D0
      Z = DCMPLX(-3D0,4*ATAN(1D0))
      WRITE (6,*) ISINTEGRALZ(Z),Z
      END


Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objInFile = objFSO.OpenTextFile(objFSO.GetParentFolderName(WScript.ScriptFullName) &_
	"\unixdict.txt",1)
Set objKeyMap = CreateObject("Scripting.Dictionary")
	With objKeyMap
		.Add "ABC", "2" : .Add "DEF", "3" : .Add "GHI", "4" : .Add "JKL", "5"
		.Add "MNO", "6" : .Add "PQRS", "7" : .Add "TUV", "8" : .Add "WXYZ", "9"
	End With

'Instantiate or Intialize Counters
TotalWords = 0
UniqueCombinations = 0
Set objUniqueWords = CreateObject("Scripting.Dictionary")
Set objMoreThanOneWord = CreateObject("Scripting.Dictionary")

Do Until objInFile.AtEndOfStream
	Word = objInFile.ReadLine
	c = 0
	Num = ""
	If Word <> "" Then
		For i = 1 To Len(Word)
			For Each Key In objKeyMap.Keys
				If InStr(1,Key,Mid(Word,i,1),1) > 0 Then
					Num = Num & objKeyMap.Item(Key)
					c = c + 1
				End If
			Next
		Next
		If c = Len(Word) Then
			TotalWords = TotalWords + 1
			If objUniqueWords.Exists(Num) = False Then
				objUniqueWords.Add Num, ""
				UniqueCombinations = UniqueCombinations + 1
			Else
				If objMoreThanOneWord.Exists(Num) = False Then
					objMoreThanOneWord.Add Num, ""
				End If
			End If
		End If
	End If
Loop

WScript.Echo "There are " & TotalWords & " words in ""unixdict.txt"" which can be represented by the digit key mapping." & vbCrLf &_
			 "They require " & UniqueCombinations & " digit combinations to represent them." & vbCrLf &_
                         objMoreThanOneWord.Count &  " digit combinations represent Textonyms."

objInFile.Close


import "io" for File
import "/str" for Char, Str
import "/sort" for Sort
import "/fmt" for Fmt

var wordList = "unixdict.txt"
var DIGITS = "22233344455566677778889999"
var map = {}
var countValid = 0
var words = File.read(wordList).trimEnd().split("\n")
for (word in words) {
    var valid = true
    var sb = ""
    for (c in Str.lower(word)) {
        if (!Char.isLower(c)) {
            valid = false
            break
        }
        sb = sb + DIGITS[Char.code(c) - 97]
    }
    if (valid) {
        countValid = countValid + 1
        if (map.containsKey(sb)) {
            map[sb].add(word)
        } else {
            map[sb] = [word]
        }
    }
}
var textonyms = map.toList.where { |me| me.value.count > 1 }.toList
var report = "There are %(countValid) words in '%(wordList)' " +
             "which can be represented by the digit key mapping.\n" +
             "They require %(map.count) digit combinations to represent them.\n" +
             "%(textonyms.count) digit combinations represent Textonyms.\n"
System.print(report)

var longest = Sort.merge(textonyms) { |i, j| (j.key.count - i.key.count).sign }
var ambiguous = Sort.merge(longest) { |i, j| (j.value.count - i.value.count).sign }

System.print("Top 8 in ambiguity: \n")
System.print("Count   Textonym  Words")
System.print("======  ========  =====")
var f = "$4d    $-8s  $s"
for (a in ambiguous.take(8)) Fmt.print(f, a.value.count, a.key, a.value)

f = f.replace("8", "14")
System.print("\nTop 6 in length:\n")
System.print("Length  Textonym        Words")
System.print("======  ==============  =====")
for (l in longest.take(6)) Fmt.print(f, l.key.count, l.key, l.value)


(defun reverse-split-at-r (xs i ys)
  (if (zp i)
      (mv xs ys)
      (reverse-split-at-r (rest xs) (1- i)
                          (cons (first xs) ys))))

(defun reverse-split-at (xs i)
  (reverse-split-at-r xs i nil))

(defun is-palindrome (str)
  (let* ((lngth (length str))
         (idx (floor lngth 2)))
    (mv-let (xs ys)
            (reverse-split-at (coerce str 'list) idx)
            (if (= (mod lngth 2) 1)
                (equal (rest xs) ys)
                (equal xs ys)))))

(include-book "testing" :dir :teachpacks)

(check-expect (is-palindrome "abba") t)
(check-expect (is-palindrome "mom") t)
(check-expect (is-palindrome "dennis sinned") t)
(check-expect (is-palindrome "palindrome") nil)
(check-expect (is-palindrome "racecars") nil)

(include-book "doublecheck" :dir :teachpacks)

(defrandom random-palindrome ()
  (let ((chars (random-list-of (random-char))))
    (coerce (append chars (reverse chars))
            'string)))

(defproperty palindrome-test
  (p :value (random-palindrome))
  (is-palindrome p))


// in FPC 3.2.0 the definition of `integer` still depends on the compiler mode
{$mode objFPC}

uses
	// used for `isInfinite`, `isNan` and `fMod`
	math,
	// NB: `ucomplex`’s `complex` isn’t a simple data type as ISO 10206 requires
	ucomplex;

{ --- determines whether a `float` value is (almost) an `integer` ------ }
function isInteger(x: float; const fuzziness: float = 0.0): Boolean;
	// nested routine allows us to spare an `if … then` statement below
	function fuzzyInteger: Boolean;
	begin
		// `x mod 1.0` uses `fMod` function from `math` unit
		x := x mod 1.0;
		result := (x <= fuzziness) or (x >= 1.0 - fuzziness);
	end;
begin
	{$push}
		// just for emphasis: use lazy evaluation strategy (currently default)
		{$boolEval off}
		result := not isInfinite(x) and not isNan(x) and fuzzyInteger;
	{$pop}
end;

{ --- check whether a `complex` number is (almost) in ℤ ---------------- }
function isInteger(const x: complex; const fuzziness: float = 0.0): Boolean;
begin
	// you could use `isZero` from the `math` unit for a fuzzy zero
	isInteger := (x.im = 0.0) and isInteger(x.re, fuzziness)
end;

{ --- test routine ----------------------------------------------------- }
procedure test(const x: float);
const
	tolerance = 0.00001;
	w = 42;
var
	s: string;
begin
	writeStr(s, 'isInteger(', x);
	writeLn(s:w, ') = ', isInteger(x):5,
		s:w, ', ', tolerance:7:5, ') = ', isInteger(x, tolerance):5);
end;

{ === MAIN ============================================================= }
begin
	test(25.000000);
	test(24.999999);
	test(25.000100);
	test(-2.1e120);
	test(-5e-2);
	test(NaN);
	test(Infinity);
	writeLn(isInteger(5.0 + 0.0 * i));
	writeLn(isInteger(5 - 5 * i));
end.


URL:="http://www.puzzlers.org/pub/wordlists/unixdict.txt";
var ZC=Import("zklCurl");
var keypad=Dictionary(
   "a",2,"b",2,"c",2,  "d",3,"e",3,"f",3,  "g",4,"h",4,"i",4,
   "j",5,"k",5,"l",5,  "m",6,"n",6,"o",6,  "p",7,"q",7,"r",7,"s",7,
   "t",8,"u",8,"v",8,  "w",9,"x",9,"y",9,"z",9);
//fcn numerate(word){ word.toLower().apply(keypad.find.fp1("")) }
fcn numerate(word){ word.toLower().apply(keypad.get) } //-->textonym or error
println("criticisms --> ",numerate("criticisms"));

words:=ZC().get(URL); //--> T(Data,bytes of header, bytes of trailer)
words=words[0].del(0,words[1]);  // remove HTTP header
println("Read %d words from %s".fmt(words.len(1),URL));

wcnt:=Dictionary();
foreach word in (words.walker(11)){  // iterate over stripped lines
   w2n:=try{ numerate(word) }catch(NotFoundError){ continue };
   wcnt.appendV(w2n,word);  // -->[textonym:list of words]
}

moreThan1Word:=wcnt.reduce(fcn(s,[(k,v)]){ s+=(v.len()>1) },0);
maxWordPerNum:=(0).max(wcnt.values.apply("len"));

("There are %d words which can be represented by the Textonyms mapping.\n"
"There are %d overlaps.").fmt(wcnt.len(),moreThan1Word).println();

println("Max collisions: %d words:".fmt(maxWordPerNum));
foreach k,v in (wcnt.filter('wrap([(k,v)]){ v.len()==maxWordPerNum })){
   println("  %s is the textonym of: %s".fmt(k,v.concat(", ")));
}


with Ada.Text_IO;

procedure Test_Function is

   function Palindrome (Text : String) return Boolean is
   begin
      for Offset in 0 .. Text'Length / 2 - 1 loop
         if Text (Text'First + Offset) /= Text (Text'Last - Offset) then
            return False;
         end if;
      end loop;
      return True;
   end Palindrome;

   str1 : String := "racecar";
   str2 : String := "wombat";

begin
   begin
      pragma Assert(False); -- raises an exception if assertions are switched on
      Ada.Text_IO.Put_Line("Skipping the test! Please compile with assertions switched on!");
   exception
      when others => -- assertions are switched on -- perform the tests
         pragma Assert (Palindrome (str1) = True,  "Assertion on str1 failed");
         pragma Assert (Palindrome (str2) = False, "Assertion on str2 failed");
         Ada.Text_IO.Put_Line("Test Passed!");
   end;
end Test_Function;


palindrome?: function [s][
    s = reverse s
]

tests: [
    [true? palindrome? "aba"]
    [false? palindrome? "ab" ]
]

loop tests => ensure


; assert.ahk
;; assert(a, b, test=2)
assert(a, b="blank", test=0)
{
  if (b = "blank")
{
    if !a
      msgbox % "blank value"
      return 0
}
    if equal_list(a, b, "`n")
      return 0
    else
    msgbox % test . ":`n" . a . "`nexpected:`n" . b
}

!r::reload

;; equal_list(a, b, delimiter)
equal_list(a, b, delimiter)
{
  loop, parse, b, %delimiter%
  {
    if instr(a, A_LoopField)
      continue
    else
      return 0
  }
  loop, parse, a, %delimiter%
  {
    if instr(b, A_LoopField)
      continue
    else
      return 0
  }

  return 1
}


package main

import (
	"fmt"
	"math"
	"math/big"
	"reflect"
	"strings"
	"unsafe"
)

// Go provides an integerness test only for the big.Rat and big.Float types
// in the standard library.

// The fundamental piece of code needed for built-in floating point types
// is a test on the float64 type:

func Float64IsInt(f float64) bool {
	_, frac := math.Modf(f)
	return frac == 0
}

// Other built-in or stanadard library numeric types are either always
// integer or can be easily tested using Float64IsInt.

func Float32IsInt(f float32) bool {
	return Float64IsInt(float64(f))
}

func Complex128IsInt(c complex128) bool {
	return imag(c) == 0 && Float64IsInt(real(c))
}

func Complex64IsInt(c complex64) bool {
	return imag(c) == 0 && Float64IsInt(float64(real(c)))
}

// Usually just the above statically typed functions would be all that is used,
// but if it is desired to have a single function that can test any arbitrary
// type, including the standard math/big types, user defined types based on
// an integer, float, or complex builtin types, or user defined types that
// have an IsInt() method, then reflection can be used.

type hasIsInt interface {
	IsInt() bool
}

var bigIntT = reflect.TypeOf((*big.Int)(nil))

func IsInt(i interface{}) bool {
	if ci, ok := i.(hasIsInt); ok {
		// Handles things like *big.Rat
		return ci.IsInt()
	}
	switch v := reflect.ValueOf(i); v.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16,
		reflect.Int32, reflect.Int64,
		reflect.Uint, reflect.Uint8, reflect.Uint16,
		reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		// Built-in types and any custom type based on them
		return true
	case reflect.Float32, reflect.Float64:
		// Built-in floats and anything based on them
		return Float64IsInt(v.Float())
	case reflect.Complex64, reflect.Complex128:
		// Built-in complexes and anything based on them
		return Complex128IsInt(v.Complex())
	case reflect.String:
		// Could also do strconv.ParseFloat then FloatIsInt but
		// big.Rat handles everything ParseFloat can plus more.
		// Note, there is no strconv.ParseComplex.
		if r, ok := new(big.Rat).SetString(v.String()); ok {
			return r.IsInt()
		}
	case reflect.Ptr:
		// Special case for math/big.Int
		if v.Type() == bigIntT {
			return true
		}
	}
	return false
}

// The rest is just demonstration and display

type intbased int16
type complexbased complex64
type customIntegerType struct {
	// Anything that stores or represents a sub-set
	// of integer values in any way desired.
}

func (customIntegerType) IsInt() bool    { return true }
func (customIntegerType) String() string { return "<…>" }

func main() {
	hdr := fmt.Sprintf("%27s  %-6s %s\n", "Input", "IsInt", "Type")
	show2 := func(t bool, i interface{}, args ...interface{}) {
		istr := fmt.Sprint(i)
		fmt.Printf("%27s  %-6t %T ", istr, t, i)
		fmt.Println(args...)
	}
	show := func(i interface{}, args ...interface{}) {
		show2(IsInt(i), i, args...)
	}

	fmt.Print("Using Float64IsInt with float64:\n", hdr)
	neg1 := -1.
	for _, f := range []float64{
		0, neg1 * 0, -2, -2.000000000000001, 10. / 2, 22. / 3,
		math.Pi,
		math.MinInt64, math.MaxUint64,
		math.SmallestNonzeroFloat64, math.MaxFloat64,
		math.NaN(), math.Inf(1), math.Inf(-1),
	} {
		show2(Float64IsInt(f), f)
	}

	fmt.Print("\nUsing Complex128IsInt with complex128:\n", hdr)
	for _, c := range []complex128{
		3, 1i, 0i, 3.4,
	} {
		show2(Complex128IsInt(c), c)
	}

	fmt.Println("\nUsing reflection:")
	fmt.Print(hdr)
	show("hello")
	show(math.MaxFloat64)
	show("9e100")
	f := new(big.Float)
	show(f)
	f.SetString("1e-3000")
	show(f)
	show("(4+0i)", "(complex strings not parsed)")
	show(4 + 0i)
	show(rune('§'), "or rune")
	show(byte('A'), "or byte")
	var t1 intbased = 5200
	var t2a, t2b complexbased = 5 + 0i, 5 + 1i
	show(t1)
	show(t2a)
	show(t2b)
	x := uintptr(unsafe.Pointer(&t2b))
	show(x)
	show(math.MinInt32)
	show(uint64(math.MaxUint64))
	b, _ := new(big.Int).SetString(strings.Repeat("9", 25), 0)
	show(b)
	r := new(big.Rat)
	show(r)
	r.SetString("2/3")
	show(r)
	show(r.SetFrac(b, new(big.Int).SetInt64(9)))
	show("12345/5")
	show(new(customIntegerType))
}


include :assert

palindrome? = { str |
  str = str.downcase.sub /\s+/ ""
  str == str.reverse
}

setup name: "palindrome test" {
  test "is a palindrome" {
    assert { palindrome? "abba" }
  }

  test "is not a palindrome" {
    assert_false { palindrome? "abb" }
  }

  test "is not a string" {
    assert_fail { palindrome? 1001 }
  }

  test "this test fails" {
    assert { palindrome? "blah blah" }
  }
}


#include <assert.h>
int IsPalindrome(char *Str);

int main()
{
    assert(IsPalindrome("racecar"));
    assert(IsPalindrome("alice"));
}


using Microsoft.VisualStudio.TestTools.UnitTesting;
using PalindromeDetector.ConsoleApp;

namespace PalindromeDetector.VisualStudioTests
{
    [TestClass]
    public class VSTests
    {
        [TestMethod]
        public void PalindromeDetectorCanUnderstandPalindrome()
        {
            //Microsoft.VisualStudio.QualityTools.UnitTestFramework v4.0.30319
            bool expected = true;
            bool actual;
            actual = Program.IsPalindrome("1");
            Assert.AreEqual(expected, actual);
            actual = Program.IsPalindromeNonRecursive("1");
            Assert.AreEqual(expected, actual);
            actual = Program.IsPalindrome("ingirumimusnocteetconsumimurigni");
            Assert.AreEqual(expected, actual);
            actual = Program.IsPalindromeNonRecursive("ingirumimusnocteetconsumimurigni");
            Assert.AreEqual(expected, actual);
        }
        [TestMethod]
        public void PalindromeDetecotryCanUnderstandNonPalindrome()
        {
            bool notExpected = true;
            bool actual = Program.IsPalindrome("ThisIsNotAPalindrome");
            Assert.AreNotEqual(notExpected, actual);
            actual = Program.IsPalindromeNonRecursive("ThisIsNotAPalindrome");
            Assert.AreNotEqual(notExpected, actual);
        }
    }
}


import Data.Decimal
import Data.Ratio
import Data.Complex


isInt =:  (= <.) *. (= {[email protected]+.)


import java.math.BigDecimal;
import java.util.List;

public class TestIntegerness {
    private static boolean isLong(double d) {
        return isLong(d, 0.0);
    }

    private static boolean isLong(double d, double tolerance) {
        return (d - Math.floor(d)) <= tolerance || (Math.ceil(d) - d) <= tolerance;
    }

    @SuppressWarnings("ResultOfMethodCallIgnored")
    private static boolean isBigInteger(BigDecimal bd) {
        try {
            bd.toBigIntegerExact();
            return true;
        } catch (ArithmeticException ex) {
            return false;
        }
    }

    private static class Rational {
        long num;
        long denom;

        Rational(int num, int denom) {
            this.num = num;
            this.denom = denom;
        }

        boolean isLong() {
            return num % denom == 0;
        }

        @Override
        public String toString() {
            return String.format("%s/%s", num, denom);
        }
    }

    private static class Complex {
        double real;
        double imag;

        Complex(double real, double imag) {
            this.real = real;
            this.imag = imag;
        }

        boolean isLong() {
            return TestIntegerness.isLong(real) && imag == 0.0;
        }

        @Override
        public String toString() {
            if (imag >= 0.0) {
                return String.format("%s + %si", real, imag);
            }
            return String.format("%s - %si", real, imag);
        }
    }

    public static void main(String[] args) {
        List<Double> da = List.of(25.000000, 24.999999, 25.000100);
        for (Double d : da) {
            boolean exact = isLong(d);
            System.out.printf("%.6f is %s integer%n", d, exact ? "an" : "not an");
        }
        System.out.println();

        double tolerance = 0.00001;
        System.out.printf("With a tolerance of %.5f:%n", tolerance);
        for (Double d : da) {
            boolean fuzzy = isLong(d, tolerance);
            System.out.printf("%.6f is %s integer%n", d, fuzzy ? "an" : "not an");
        }
        System.out.println();

        List<Double> fa = List.of(-2.1e120, -5e-2, Double.NaN, Double.POSITIVE_INFINITY);
        for (Double f : fa) {
            boolean exact = !f.isNaN() && !f.isInfinite() && isBigInteger(new BigDecimal(f.toString()));
            System.out.printf("%s is %s integer%n", f, exact ? "an" : "not an");
        }
        System.out.println();

        List<Complex> ca = List.of(new Complex(5.0, 0.0), new Complex(5.0, -5.0));
        for (Complex c : ca) {
            boolean exact = c.isLong();
            System.out.printf("%s is %s integer%n", c, exact ? "an" : "not an");
        }
        System.out.println();

        List<Rational> ra = List.of(new Rational(24, 8), new Rational(-5, 1), new Rational(17, 2));
        for (Rational r : ra) {
            boolean exact = r.isLong();
            System.out.printf("%s is %s integer%n", r, exact ? "an" : "not an");
        }
    }
}


#include <algorithm>
#include <string>

constexpr bool is_palindrome(std::string_view s)
{
  return std::equal(s.begin(), s.begin()+s.length()/2, s.rbegin());
}


(use 'clojure.test)

(deftest test-palindrome?
  (is (palindrome? "amanaplanacanalpanama"))
  (is (not (palindrome? "Test 1, 2, 3")))

(run-tests)


(defpackage :rosetta
  (:use :cl
        :fiveam))
(in-package :rosetta)

(defun palindromep (string)
  (string= string (reverse string)))

;; A suite of tests are declared with DEF-SUITE
(def-suite palindrome-suite :description "Tests for PALINDROMEP")

;; Tests following IN-SUITE are in the defined suite of tests
(in-suite palindrome-suite)

;; Tests are declared with TEST and take an optional documentation
;; string
(test palindromep
  "Basic unit tests for PALINDROMEP."
  (is-true (palindromep "a"))
  (is-true (palindromep ""))
  (is-true (palindromep "aba"))
  (is-true (palindromep "ahha"))
  (is-true (palindromep "amanaplanacanalpanama"))
  (is-false (palindromep "ab"))
  (is-false (palindromep "abcab")))

(test palindromep-bad-tests
  "In order to demonstrate a failing test"
  (is-true (palindromep "ab")))

;; Property based tests are also possible using built-in generators
(test matches-even-length-palindromes
  (for-all ((s (gen-string)))
    (is-true (palindromep (concatenate 'string s (reverse s))))))

;; And counter examples can be found for failing tests. This also
;; demonstrates combining generators to create cleaner input, in this
;; case restricting characters to the range of ASCII characters and
;; only permitting alphanumeric values.
(test matches-even-length-palindromes-bad
  (for-all ((s (gen-string :elements (gen-character :code (gen-integer :min 0 :max 127) :alphanumericp t))))
    (is-true (palindromep (concatenate 'string s s)))))

#|
Tests can be executed using RUN, RUN!, and (EXPLAIN! result-list)

RUN! = (EXPLAIN! (RUN test))

Individual tests can be run or the entire suite:

ROSETTA> (run! 'palindrome-suite)

Running test suite PALINDROME-SUITE
 Running test PALINDROMEP .......
 Running test PALINDROMEP-BAD-TESTS f
 Running test MATCHES-EVEN-LENGTH-PALINDROMES .....................................................................................................
 Running test MATCHES-EVEN-LENGTH-PALINDROMES-BAD ff
 Did 10 checks.
    Pass: 8 (80%)
    Skip: 0 ( 0%)
    Fail: 2 (20%)

 Failure Details:
 --------------------------------
 MATCHES-EVEN-LENGTH-PALINDROMES-BAD []:
      Falsifiable with ("oMYhcqnVbjYgxT6d3").
 Results collected with failure data:
    Did 1 check.
       Pass: 0 ( 0%)
       Skip: 0 ( 0%)
       Fail: 1 (100%)

    Failure Details:
    --------------------------------
    MATCHES-EVEN-LENGTH-PALINDROMES-BAD []:
         (PALINDROMEP (CONCATENATE 'STRING S S)) did not return a true value.
    --------------------------------

 --------------------------------
 --------------------------------
 PALINDROMEP-BAD-TESTS [In order to demonstrate a failing test]:
      (PALINDROMEP "ab") did not return a true value.
 --------------------------------

NIL
(#<IT.BESE.FIVEAM::TEST-FAILURE {10083B52A3}>
 #<IT.BESE.FIVEAM::FOR-ALL-TEST-FAILED {1008B34963}>)
NIL
ROSETTA> (run! 'palindromep)

Running test PALINDROMEP .......
 Did 7 checks.
    Pass: 7 (100%)
    Skip: 0 ( 0%)
    Fail: 0 ( 0%)

T
NIL
NIL
|#


def is_integral:
  if type == "number" then . == floor
  elif type == "array" then
       length == 2 and .[1] == 0 and (.[0] | is_integral)
  else type == "object"
       and .type == "rational"
       and  .q != 0
       and (.q | is_integral)
       and ((.p / .q) | is_integral)
  end ;


require "spec"

describe "palindrome" do
  it "returns true for a word that's palindromic" do
    palindrome("racecar").should be_true
  end

  it "returns false for a word that's not palindromic" do
    palindrome("goodbye").should be_false
  end
end

def palindrome(s)
  s == s.reverse
end


unittest {
  assert(isPalindrome("racecar"));
  assert(isPalindrome("bob"));
  assert(!isPalindrome("alice"));
}


  Assert(IsPalindrome('salàlas'), 'salàlas is a valid palindrome');
  Assert(IsPalindrome('Ingirumimusnocteetconsumimurigni'), 'Ingirumimusnocteetconsumimurigni is a valid palindrome');
  Assert(not IsPalindrome('123'), '123 is not a valid palindrome');


#!/usr/bin/env rune

? def isPalindrome(string :String) {
>   def upper := string.toUpperCase()
>   def last := upper.size() - 1
>   for i => c ? (upper[last - i] != c) in upper(0, upper.size() // 2) {
>     return false
>   }
>   return true
> }

? isPalindrome("")
# value: true

? isPalindrome("a")
# value: true

? isPalindrome("aa")
# value: true

? isPalindrome("baa")
# value: false

? isPalindrome("baab")
# value: true

? isPalindrome("ba_ab")
# value: true

? isPalindrome("ba_ ab")
# value: false

? isPalindrome("ba _ ab")
# value: true

? isPalindrome("ab"*2)
# value: false

? def x := "ab" * 2**15; null

? x.size()
# value: 65536

? def xreversed := "ba" * 2**15; null

? isPalindrome(x + xreversed)
# value: true

? (x + xreversed).size()
# value: 131072


# v0.6.0

@show isinteger(25.000000)
@show isinteger(24.999999)
@show isinteger(25.000100)
@show isinteger(-2.1e120)
@show isinteger(-5e-2)
@show isinteger(NaN)
@show isinteger(Inf)
@show isinteger(complex(5.0, 0.0))
@show isinteger(complex(5, 5))


// version 1.1.2

import java.math.BigInteger
import java.math.BigDecimal

fun Double.isLong(tolerance: Double = 0.0) =
    (this - Math.floor(this)) <= tolerance || (Math.ceil(this) - this) <= tolerance

fun BigDecimal.isBigInteger() =
    try {
        this.toBigIntegerExact()
        true
    }
    catch (ex: ArithmeticException) {
        false
    }

class Rational(val num: Long, val denom: Long) {
    fun isLong() = num % denom == 0L

    override fun toString() = "$num/$denom"
}

class Complex(val real: Double, val imag: Double) {
    fun isLong() = real.isLong() && imag == 0.0

    override fun toString() =
        if (imag >= 0.0)
            "$real + ${imag}i"
        else
            "$real - ${-imag}i"
}

fun main(args: Array<String>) {
    val da = doubleArrayOf(25.000000, 24.999999, 25.000100)
    for (d in da) {
        val exact = d.isLong()
        println("${"%.6f".format(d)} is ${if (exact) "an" else "not an"} integer")
    }
    val tolerance = 0.00001
    println("\nWith a tolerance of ${"%.5f".format(tolerance)}:")
    for (d in da) {
        val fuzzy = d.isLong(tolerance)
        println("${"%.6f".format(d)} is ${if (fuzzy) "an" else "not an"} integer")
    }

    println()
    val fa = doubleArrayOf(-2.1e120, -5e-2, Double.NaN, Double.POSITIVE_INFINITY)
    for (f in fa) {
        val exact = if (f.isNaN() || f.isInfinite()) false
                    else BigDecimal(f.toString()).isBigInteger()
        println("$f is ${if (exact) "an" else "not an"} integer")
    }

    println()
    val ca = arrayOf(Complex(5.0, 0.0), Complex(5.0, -5.0))
    for (c in ca) {
        val exact = c.isLong()
        println("$c is ${if (exact) "an" else "not an"} integer")
    }

    println()
    val ra = arrayOf(Rational(24, 8), Rational(-5, 1), Rational(17, 2))
    for (r in ra) {
        val exact = r.isLong()
        println("$r is ${if (exact) "an" else "not an"} integer")
    }
}


(assert (palindrome? "aba")) → #t
(assert (palindrome? "abbbca") "palindrome fail")
💥 error: palindrome fail : assertion failed : (palindrome? abbbca)

(check-expect (palindrome? "aba") #t) → #t
(check-expect (palindrome? "abcda") #f) → #t
(check-expect (palindrome? "abcda") #t)
😐 warning: #t : check failed : (palindrome? abcda) → #f
(assert (palindrome? "un roc lamina l animal cornu")) → #t


-module( palindrome_tests ).
-compile( export_all ).
-include_lib( "eunit/include/eunit.hrl" ).

abcba_test() -> ?assert( palindrome:is_palindrome("abcba") ).

abcdef_test() -> ?assertNot( palindrome:is_palindrome("abcdef") ).


--unittest in standard library 4.0+
include std/unittest.e
include palendrome.e  --routines to be tested

object p = "12321"

test_equal("12321", 1, isPalindrome(p))
test_equal("r12321", 1, isPalindrome(reverse(p)))

test_report()


let palindrome (s : string) =
    let a = s.ToUpper().ToCharArray()
    Array.rev a = a

open NUnit.Framework

[<TestFixture>]
type TestCases() =
    [<Test>]
    member x.Test01() =
        Assert.IsTrue(palindrome "radar")

    [<Test>]
    member x.Test02() =
        Assert.IsFalse(palindrome "hello")


function isInt (x) return type(x) == "number" and x == math.floor(x) end

print("Value\tInteger?")
print("=====\t========")
local testCases = {2, 0, -1, 3.5, "String!", true}
for _, input in pairs(testCases) do print(input, isInt(input)) end


import complex, rationals, math, fenv, sugar

func isInteger[T: Complex | Rational | SomeNumber](x: T; tolerance = 0f64): bool =
  when T is Complex:
    x.im == 0 and x.re.isInteger
  elif T is Rational:
    x.dup(reduce).den == 1
  elif T is SomeFloat:
    ceil(x) - x <= tolerance
  elif T is SomeInteger:
    true

# Floats.
assert not NaN.isInteger
assert not INF.isInteger      # Indeed, "ceil(INF) - INF" is NaN.
assert not (-5e-2).isInteger
assert (-2.1e120).isInteger
assert 25.0.isInteger
assert not 24.999999.isInteger
assert 24.999999.isInteger(tolerance = 0.00001)
assert not (1f64 + epsilon(float64)).isInteger
assert not (1f32 - epsilon(float32)).isInteger
# Rationals.
assert not (5 // 3).isInteger
assert (9 // 3).isInteger
assert (-143 // 13).isInteger
# Unsigned integers.
assert 3u.isInteger
# Complex numbers.
assert not (1.0 + im 1.0).isInteger
assert (5.0 + im 0.0).isInteger


/* REXX ---------------------------------------------------------------
* 22.06.2014 Walter Pachl using a complex data class
* ooRexx Distribution contains an elaborate complex class
* parts of which are used here
* see REXX for Extra Credit implementation
*--------------------------------------------------------------------*/
Numeric Digits 1000
Call test_integer .complex~new(1e+12,0e-3)
Call test_integer .complex~new(3.14)
Call test_integer .complex~new(1.00000)
Call test_integer .complex~new(33)
Call test_integer .complex~new(999999999)
Call test_integer .complex~new(99999999999)
Call test_integer .complex~new(1e272)
Call test_integer .complex~new(0)
Call test_integer .complex~new(1.000,-3)
Call test_integer .complex~new(1.000,-3.3)
Call test_integer .complex~new(,4)
Call test_integer .complex~new(2.00000000,+0)
Call test_integer .complex~new(,0)
Call test_integer .complex~new(333)
Call test_integer .complex~new(-1,-1)
Call test_integer .complex~new(1,1)
Call test_integer .complex~new(,.00)
Call test_integer .complex~new(,1)
Call test_integer .complex~new(0003,00.0)
Exit

test_integer:
Use Arg cpx
cpxa=left(changestr('+-',cpx,'-'),13)  -- beautify representation
Select
  When cpx~imaginary<>0 Then
    Say cpxa 'is not an integer'
  When datatype(cpx~real,'W') Then
    Say cpxa 'is an integer'
  Otherwise
    Say cpxa 'is not an integer'
  End
Return

::class complex

::method init                               /* initialize a complex number    */
expose real imaginary                       /* expose the state data          */
use Strict arg first=0, second=0            /* access the two numbers         */
real = first + 0                            /* force rounding                 */
imaginary = second + 0                      /* force rounding on the second   */

::method real                               /* return real part of a complex  */
expose real                                 /* access the state information   */
return real                                 /* return that value              */

::method imaginary                          /* return imaginary part          */
expose imaginary                            /* access the state information   */
return imaginary                            /* return the value               */

::method string                             /* format as a string value       */
expose real imaginary                       /* get the state info             */
return real'+'imaginary'i'                  /* format as real+imaginaryi      */


USING: kernel sequences ;
IN: palindrome

: palindrome? ( string -- ? ) dup reverse = ;


class TestPalindrome : Test
{
  public Void testIsPalindrome ()
  {
    verify(Palindrome.isPalindrome(""))
    verify(Palindrome.isPalindrome("a"))
    verify(Palindrome.isPalindrome("aa"))
    verify(Palindrome.isPalindrome("aba"))
    verifyFalse(Palindrome.isPalindrome("abb"))
    verify(Palindrome.isPalindrome("salàlas"))
    verify(Palindrome.isPalindrome("In girum imus nocte et consumimur igni".lower.replace(" ","")))
  }
}


Sub StrReverse(Byref text As String)
    Dim As Integer x, lt = Len(text)
    For x = 0 To lt Shr 1 - 1
        Swap text[x], text[lt - x - 1]
    Next x

End Sub

Sub Replace(Byref T As String, Byref I As String, Byref S As String, Byval A As Integer = 1)
    Var p = Instr(A, T, I), li = Len(I), ls = Len(S) : If li = ls Then li = 0
    Do While p
        If li Then T = Left(T, p - 1) & S & Mid(T, p + li) Else Mid(T, p) = S
        p = Instr(p + ls, T, I)
    Loop
End Sub

Function IsPalindrome(Byval txt As String) As Boolean
    Dim As String tempTxt = Lcase(txt), copyTxt = Lcase(txt)
    Replace(tempTxt, " ", "")
    Replace(copyTxt, " ", "")

    StrReverse(tempTxt)
    If tempTxt = copyTxt Then
        Color 10
        Return true
    Else
        Color 12
        Return false
    End If
End Function

'--- Programa Principal ---
Dim As String a(10) => {"abba", "mom", "dennis sinned", "Un roc lamina l animal cornu", _
"palindrome", "ba _ ab", "racecars", "racecar", "wombat", "in girum imus nocte et consumimur igni"}

Print !"¨Pal¡ndromos?\n"
For i As Byte = 0 To Ubound(a)-1
    Print a(i) & " -> ";
    Print IsPalindrome((a(i)))
    Color 7
Next i
Sleep


V debug = 0B
V datePat = re:‘\d{4}-\d{2}-\d{2}’
V valuPat = re:‘[-+]?\d+\.\d+’
V statPat = re:‘-?\d+’
V totalLines = 0
Set[String] dupdate
Set[String] badform
Set[String] badlen
V badreading = 0
Set[String] datestamps

L(line) File(‘readings.txt’).read().rtrim("\n").split("\n")
   totalLines++
   V fields = line.split("\t")
   V date = fields[0]
   V pairs = (1 .< fields.len).step(2).map(i -> (@fields[i], @fields[i + 1]))

   V lineFormatOk = datePat.match(date)
      & all(pairs.map(p -> :valuPat.match(p[0])))
      & all(pairs.map(p -> :statPat.match(p[1])))
   I !lineFormatOk
      I debug
         print(‘Bad formatting ’line)
      badform.add(date)

   I pairs.len != 24 | any(pairs.map(p -> Int(p[1]) < 1))
      I debug
         print(‘Missing values ’line)
   I pairs.len != 24
      badlen.add(date)
   I any(pairs.map(p -> Int(p[1]) < 1))
      badreading++

   I date C datestamps
      I debug
         print(‘Duplicate datestamp ’line)
      dupdate.add(date)

   datestamps.add(date)

print("Duplicate dates:\n  "sorted(Array(dupdate)).join("\n  "))
print("Bad format:\n  "sorted(Array(badform)).join("\n  "))
print("Bad number of fields:\n  "sorted(Array(badlen)).join("\n  "))
print("Records with good readings: #. = #2.2%\n".format(
   totalLines - badreading, (totalLines - badreading) / Float(totalLines) * 100))
print(‘Total records:  ’totalLines)


use Math::Complex;

sub is_int {
    my $number = shift;

    if (ref $number eq 'Math::Complex') {
        return 0 if $number->Im != 0;
        $number = $number->Re;
    }

    return int($number) == $number;
}

for (5, 4.1, sqrt(2), sqrt(4), 1.1e10, 3.0-0.0*i, 4-3*i, 5.6+0*i) {
    printf "%20s is%s an integer\n", $_, (is_int($_) ? "" : " NOT");
}


package pal

import "testing"

func TestPals(t *testing.T) {
    pals := []string{
        "",
        ".",
        "11",
        "ere",
        "ingirumimusnocteetconsumimurigni",
    }
    for _, s := range pals {
        if !IsPal(s) {
            t.Error("IsPal returned false on palindrome,", s)
        }
    }
}

func TestNonPals(t *testing.T) {
    nps := []string{
        "no",
        "odd",
        "salàlas",
    }
    for _, s := range nps {
        if IsPal(s) {
            t.Error("IsPal returned true on non-palindrome,", s)
        }
    }
}


with Ada.Calendar;           use Ada.Calendar;
with Ada.Text_IO;            use Ada.Text_IO;
with Strings_Edit;           use Strings_Edit;
with Strings_Edit.Floats;    use Strings_Edit.Floats;
with Strings_Edit.Integers;  use Strings_Edit.Integers;

with Generic_Map;

procedure Data_Munging_2 is
   package Time_To_Line is new Generic_Map (Time, Natural);
   use Time_To_Line;
   File    : File_Type;
   Line_No : Natural := 0;
   Count   : Natural := 0;
   Stamps  : Map;
begin
   Open (File, In_File, "readings.txt");
   loop
      declare
         Line    : constant String := Get_Line (File);
         Pointer : Integer := Line'First;
         Flag    : Integer;
         Year, Month, Day : Integer;
         Data    : Float;
         Stamp   : Time;
         Valid   : Boolean := True;
      begin
         Line_No := Line_No + 1;
         Get (Line, Pointer, SpaceAndTab);
         Get (Line, Pointer, Year);
         Get (Line, Pointer, Month);
         Get (Line, Pointer, Day);
         Stamp := Time_Of (Year_Number (Year), Month_Number (-Month), Day_Number (-Day));
         begin
            Add (Stamps, Stamp, Line_No);
         exception
            when Constraint_Error =>
               Put (Image (Year) & Image (Month) & Image (Day) & ": record at " & Image (Line_No));
               Put_Line (" duplicates record at " & Image (Get (Stamps, Stamp)));
         end;
         Get (Line, Pointer, SpaceAndTab);
         for Reading in 1..24 loop
            Get (Line, Pointer, Data);
            Get (Line, Pointer, SpaceAndTab);
            Get (Line, Pointer, Flag);
            Get (Line, Pointer, SpaceAndTab);
            Valid := Valid and then Flag >= 1;
         end loop;
         if Pointer <= Line'Last then
            Put_Line ("Unrecognized tail at " & Image (Line_No) & ':' & Image (Pointer));
         elsif Valid then
            Count := Count + 1;
         end if;
      exception
         when End_Error | Data_Error | Constraint_Error | Time_Error =>
            Put_Line ("Syntax error at " & Image (Line_No) & ':' & Image (Pointer));
      end;
   end loop;
exception
   when End_Error =>
      Close (File);
      Put_Line ("Valid records " & Image (Count) & " of " & Image (Line_No) & " total");
end Data_Munging_2;


program integerness(output);

{ determines whether a `complex` also fits in `integer` ---------------- }
function isRealIntegral(protected x: complex): Boolean;
begin
	{ It constitutes an error if no value for `trunc(x)` exists, }
	{ thus check re(x) is in the range -maxInt..maxInt first. }
	isRealIntegral := (im(x) = 0.0) and_then
		(abs(re(x)) <= maxInt * 1.0) and_then
		(trunc(re(x)) * 1.0 = re(x))
end;

{ calls isRealIntegral with zero imaginary part ------------------------ }
function isIntegral(protected x: real): Boolean;
begin
	isIntegral := isRealIntegral(cmplx(x * 1.0, 0.0))
end;

{ Rosetta code test ---------------------------------------------------- }
procedure test(protected x: complex);
begin
	writeLn(re(x), ' + ', im(x), ' 𝒾 : ',
		isIntegral(re(x)), ' ', isRealIntegral(x))
end;

{ === MAIN ============================================================= }
begin
	test(cmplx(25.0, 0.0));
	test(cmplx(24.999999, 0.0));
	test(cmplx(25.000100, 0.0));
	test(cmplx(-2.1E120, 0.0));
	test(cmplx(-5E-2, 0.0));
	test(cmplx(5.0, 0.0));
	test(cmplx(5, -5));
end.


import Test.QuickCheck

isPalindrome :: String -> Bool
isPalindrome x = x == reverse x

{- There is no built-in definition of how to generate random characters;
   here we just specify ASCII characters. Generating strings then automatically
   follows from the definition of String as list of Char. -}
instance Arbitrary Char where
  arbitrary = choose ('\32', '\127')

--                                            /------------------------- the randomly-generated parameters
--                                            |      /------------------ the constraint on the test values
--                                            |      |                /- the condition which should be true
--                                            v      v                v
main = do
  putStr "Even palindromes: " >> quickCheck (\s   ->                  isPalindrome (s ++ reverse s))
  putStr "Odd palindromes:  " >> quickCheck (\s   -> not (null s) ==> isPalindrome (s ++ (tail.reverse) s))
  putStr "Non-palindromes:  " >> quickCheck (\i s -> not (null s) && 0 <= i && i < length s && i*2 /= length s
                                                                  ==> not (isPalindrome (take i s ++ "•" ++ drop i s)))


procedure main()
    s := "ablewasiereisawelba"
    assert{"test1",palindrome(s)}
    assertFailure{"test2",palindrome(s)}
    s := "un"||s
    assert{"test3",palindrome(s)}
    assertFailure{"test4",palindrome(s)}
end

procedure palindrome(s)
    return s == reverse(s)
end

procedure assert(A)
    if not @A[2] then write(@A[1],": failed")
end

procedure assertFailure(A)
    if @A[2] then write(@A[1],": failed")
end


check_format(list l)
{
    integer i;
    text s;

    if (~l != 49) {
        error("bad field count");
    }

    s = l[0];
    if (match("????-??-??", s)) {
        error("bad date format");
    }
    l[0] = s.delete(7).delete(4).atoi;

    i = 1;
    while (i < 49) {
        atof(l[i]);
        i += 1;
        l[i >> 1] = atoi(l[i]);
        i += 1;
    }

    l.erase(25, -1);
}

main(void)
{
    integer goods, i, v;
    file f;
    list l;
    index x;

    goods = 0;

    f.affix("readings.txt");

    while (f.list(l, 0) != -1) {
        if (!trap(check_format, l)) {
            if ((x[v = lf_x_integer(l)] += 1) != 1) {
                v_form("duplicate ~ line\n", v);
            }

            i = 1;
            l.ucall(min_i, 1, i);
            goods += iclip(0, i, 1);
        }
    }

    o_(goods, " good lines\n");

    0;
}


; Author: AlephX Aug 17 2011
data = %A_scriptdir%\readings.txt

Loop, Read, %data%
	{
	Lines := A_Index
    StringReplace, dummy, A_LoopReadLine, %A_Tab%,, All UseErrorLevel

    Loop, parse, A_LoopReadLine, %A_Tab%
		{
		wrong := 0
		if A_index = 1
			{
			Date := A_LoopField
			if (Date == OldDate)
				{
				WrongDates = %WrongDates%%OldDate% at %Lines%`n
				TotwrongDates++
				Wrong := 1
				break
				}
			}
		else
			{
			if (A_loopfield/1 < 0)
				{
				Wrong := 1
				break
				}

			}
		}

	if (wrong == 1)
		totwrong++
	else
		valid++

	if (errorlevel <> 48)
		{
		if (wrong == 0)
			{
			totwrong++
			valid--
			}
		unvalidformat++
		}

	olddate := date
	}

msgbox, Duplicate Dates:`n%wrongDates%`nRead Lines: %lines%`nValid Lines: %valid%`nwrong lines: %totwrong%`nDuplicates: %TotWrongDates%`nWrong Formatted: %unvalidformat%`n


(de int? (N)
  (= N (* 1.0 (/ N 1.0)))) #returns T or NIL

(de integer? (N)
  (and (= N (* 1.0 (/ N 1.0))) N)) #returns value of N or NIL

(scl 4) #-> 4 # *Scl the global which holds
1.0 #-> 10000
(int? 1.0) #-> T
(int? 1) #-> NIL # 1 with a scale of 4 is same as 0.0001 which is not an Integer
(int? -1.0) #-> T
(int? -0.0) #-> T
(int? "RE") #-> "RE" -- Number expected
(int? (*/ 2.0 1.0 3.0)) #-> NIL # 6667 is not an integer of the scale of 4, use of */ because of the scale


function Test-Integer ($Number)
{
    try
    {
        $Number = [System.Numerics.Complex]$Number

        if (($Number.Real -eq [int]$Number.Real) -and ($Number.Imaginary -eq 0))
        {
            return $true
        }
        else
        {
            return $false
        }
    }
    catch
    {
        Write-Host "Parameter was not a number."
    }
}


NB. Contents of palindrome_test.ijs

NB. Basic testing
test_palinA=: monad define
  assert isPalin0 'abcba'
  assert isPalin0 'aa'
  assert isPalin0 ''
  assert -. isPalin0 'ab'
  assert -. isPalin0 'abcdba'
)

NB. Can test for expected failure instead
palinB_expect=: 'assertion failure'
test_palinB=: monad define
  assert isPalin0 'ab'
)


import static ExampleClass.pali; // or from wherever it is defined
import static ExampleClass.rPali; // or from wherever it is defined
import org.junit.*;
public class PalindromeTest extends junit.framework.TestCase {
    @Before
    public void setUp(){
        //runs before each test
        //set up instance variables, network connections, etc. needed for all tests
    }
    @After
    public void tearDown(){
        //runs after each test
        //clean up instance variables (close files, network connections, etc.).
    }

    /**
     * Test the pali(...) method.
     */
    @Test
    public void testNonrecursivePali() throws Exception {
        assertTrue(pali("abcba"));
        assertTrue(pali("aa"));
        assertTrue(pali("a"));
        assertTrue(pali(""));
        assertFalse(pali("ab"));
        assertFalse(pali("abcdba"));
    }
    /**
     * Test the rPali(...) method.
     */
    @Test
    public void testRecursivePali() throws Exception {
        assertTrue(rPali("abcba"));
        assertTrue(rPali("aa"));
        assertTrue(rPali("a"));
        assertTrue(rPali(""));
        assertFalse(rPali("ab"));
        assertFalse(rPali("abcdba"));
    }

    /**
     * Expect a WhateverExcpetion
     */
    @Test(expected=WhateverException.class)
    public void except(){
        //some code that should throw a WhateverException
    }
}


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

typedef struct { const char *s; int ln, bad; } rec_t;
int cmp_rec(const void *aa, const void *bb)
{
	const rec_t *a = aa, *b = bb;
	return a->s == b->s ? 0 : !a->s ? 1 : !b->s ? -1 : strncmp(a->s, b->s, 10);
}

int read_file(const char *fn)
{
	int fd = open(fn, O_RDONLY);
	if (fd == -1) return 0;

	struct stat s;
	fstat(fd, &s);

	char *txt = malloc(s.st_size);
	read(fd, txt, s.st_size);
	close(fd);

	int i, j, lines = 0, k, di, bad;
	for (i = lines = 0; i < s.st_size; i++)
		if (txt[i] == '\n') {
			txt[i] = '\0';
			lines++;
		}

	rec_t *rec = calloc(sizeof(rec_t), lines);
	const char *ptr, *end;
	rec[0].s = txt;
	rec[0].ln = 1;
	for (i = 0; i < lines; i++) {
		if (i + 1 < lines) {
			rec[i + 1].s = rec[i].s + strlen(rec[i].s) + 1;
			rec[i + 1].ln = i + 2;
		}
		if (sscanf(rec[i].s, "%4d-%2d-%2d", &di, &di, &di) != 3) {
			printf("bad line %d: %s\n", i, rec[i].s);
			rec[i].s = 0;
			continue;
		}
		ptr = rec[i].s + 10;

		for (j = k = 0; j < 25; j++) {
			if (!strtod(ptr, (char**)&end) && end == ptr) break;
			k++, ptr = end;
			if (!(di = strtol(ptr, (char**)&end, 10)) && end == ptr) break;
			k++, ptr = end;
			if (di < 1) rec[i].bad = 1;
		}

		if (k != 48) {
			printf("bad format at line %d: %s\n", i, rec[i].s);
			rec[i].s = 0;
		}
	}

	qsort(rec, lines, sizeof(rec_t), cmp_rec);
	for (i = 1, bad = rec[0].bad, j = 0; i < lines && rec[i].s; i++) {
		if (rec[i].bad) bad++;
		if (strncmp(rec[i].s, rec[j].s, 10)) {
			j = i;
		} else
			printf("dup line %d: %.10s\n", rec[i].ln, rec[i].s);
	}

	free(rec);
	free(txt);
	printf("\n%d out %d lines good\n", lines - bad, lines);
	return 0;
}

int main()
{
	read_file("readings.txt");
	return 0;
}


>>> def isint(f):
    return complex(f).imag == 0 and complex(f).real.is_integer()

>>> [isint(f) for f in (1.0, 2, (3.0+0.0j), 4.1, (3+4j), (5.6+0j))]
[True, True, True, False, False, False]

>>> # Test cases
...
>>> isint(25.000000)
True
>>> isint(24.999999)
False
>>> isint(25.000100)
False
>>> isint(-2.1e120)
True
>>> isint(-5e-2)
False
>>> isint(float('nan'))
False
>>> isint(float('inf'))
False
>>> isint(5.0+0.0j)
True
>>> isint(5-5j)
False


  [ $ "bigrat.qky" loadfile ] now!

  [ mod not ]                   is v-is-num (    n/d --> b )

  [ 1+ dip [ proper rot drop ]
    10 swap ** round v-is-num ] is approxint ( n/d n --> b )


const assert = require('assert');

describe('palindrome', () => {
  const pali = require('../lib/palindrome');

  describe('.check()', () => {
    it('should return true on encountering a palindrome', () => {
      assert.ok(pali.check('racecar'));
      assert.ok(pali.check('abcba'));
      assert.ok(pali.check('aa'));
      assert.ok(pali.check('a'));
    });

    it('should return true on encountering an empty string', () => {
      assert.ok(pali.check(''));
    });

    it('should return false on encountering a non-palindrome', () => {
      assert.ok(!pali.check('alice'));
      assert.ok(!pali.check('ab'));
      assert.ok(!pali.check('abcdba'));
    });
  })
});


# Test case 1:
.
1
1

# Test case 2:
1+1
null
2

# Test case 3 (with the wrong result):
1+1
null
0

# A test case with a function definition:
def factorial: if . <= 0 then 1 else . * ((. - 1) | factorial) end; factorial
3
6


using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.IO;

namespace TextProc2
{
    class Program
    {
        static void Main(string[] args)
        {
            Regex multiWhite = new Regex(@"\s+");
            Regex dateEx = new Regex(@"^\d{4}-\d{2}-\d{2}$");
            Regex valEx = new Regex(@"^\d+\.{1}\d{3}$");
            Regex flagEx = new Regex(@"^[1-9]{1}$");

            int missformcount = 0, totalcount = 0;
            Dictionary<int, string> dates = new Dictionary<int, string>();

            using (StreamReader sr = new StreamReader("readings.txt"))
            {
                string line = sr.ReadLine();
                while (line != null)
                {
                    line = multiWhite.Replace(line, @" ");
                    string[] splitLine = line.Split(' ');
                    if (splitLine.Length != 49)
                        missformcount++;
                    if (!dateEx.IsMatch(splitLine[0]))
                        missformcount++;
                    else
                        dates.Add(totalcount + 1, dateEx.Match(splitLine[0]).ToString());
                    int err = 0;
                    for (int i = 1; i < splitLine.Length; i++)
                    {
                        if (i%2 != 0)
                        {
                            if (!valEx.IsMatch(splitLine[i]))
                                err++;
                        }
                        else
                        {
                            if (!flagEx.IsMatch(splitLine[i]))
                                err++;
                        }
                    }
                    if (err != 0) missformcount++;
                    line = sr.ReadLine();
                    totalcount++;
                }
            }

            int goodEntries = totalcount - missformcount;
            Dictionary<string,List<int>> dateReverse = new Dictionary<string,List<int>>();

            foreach (KeyValuePair<int, string> kvp in dates)
            {
                if (!dateReverse.ContainsKey(kvp.Value))
                    dateReverse[kvp.Value] = new List<int>();
                dateReverse[kvp.Value].Add(kvp.Key);
            }

            Console.WriteLine(goodEntries + " valid Records out of " + totalcount);

            foreach (KeyValuePair<string, List<int>> kvp in dateReverse)
            {
                if (kvp.Value.Count > 1)
                    Console.WriteLine("{0} is duplicated at Lines : {1}", kvp.Key, string.Join(",", kvp.Value));
            }
        }
    }
}


#lang racket
(require tests/eli-tester)

(test ;; known representations of integers:
 ;; - as exacts
 (integer? -1) => #t
 (integer?  0) => #t
 (integer?  1) => #t
 (integer?   1234879378539875943875937598379587539875498792424323432432343242423432432) => #t
 (integer?  -1234879378539875943875937598379587539875498792424323432432343242423432432) => #t
 (integer?  #xff) => #t

 ;; - as inexacts
 (integer? -1.) => #t
 (integer?  0.) => #t
 (integer?  1.) => #t
 (integer?  1234879378539875943875937598379587539875498792424323432432343242423432432.) => #t
 (integer?  #xff.0) => #t
 ;; - but without a decimal fractional part
 (integer? -1.1) => #f

 ;; - fractional representation
 (integer? -42/3) => #t
 (integer?   0/1) => #t
 (integer?  27/9) => #t
 (integer?  #xff/f) => #t
 (integer?  #b11111111/1111) => #t
 ;; - but obviously not fractions
 (integer? 5/7) => #f

 ; - as scientific
 (integer?  1.23e2) => #t
 (integer?  1.23e120) => #t
 ; - but not with a small exponent
 (integer?  1.23e1) => #f

 ; - complex representations with 0 imaginary component
 ;   ℤ is a subset of the sets of rational and /real/ numbers and
 (integer? 1+0i) => #t
 (integer? (sqr 0+1i)) => #t
 (integer? 0+1i) => #f

 ;; oh, there's so much else that isn't an integer:
 (integer? "woo") => #f
 (integer? "100") => #f
 (integer? (string->number "22/11")) => #t ; just cast it!
 (integer? +inf.0) => #f
 (integer? -inf.0) => #f
 (integer? +nan.0) => #f ; duh! it's not even a number!
 (integer? -NaN.0) => #f
 (integer? pi) => #f
 )


multi is-int ($n) { $n.narrow ~~ Int }

multi is-int ($n, :$tolerance!) {
    abs($n.round - $n) <= $tolerance
}

multi is-int (Complex $n, :$tolerance!) {
    is-int($n.re, :$tolerance) && abs($n.im) < $tolerance
}

# Testing:

for 25.000000, 24.999999, 25.000100, -2.1e120, -5e-2, Inf, NaN, 5.0+0.0i, 5-5i {
    printf "%-7s  %-9s  %-5s  %-5s\n", .^name, $_,
        is-int($_),
        is-int($_, :tolerance<0.00001>);
}


/* REXX ---------------------------------------------------------------
* 20.06.2014 Walter Pachl
* 22.06.2014 WP add complex numbers such as 13-12j etc.
* (using 13e-12 or so is not (yet) supported)
*--------------------------------------------------------------------*/
Call test_integer 3.14
Call test_integer 1.00000
Call test_integer 33
Call test_integer 999999999
Call test_integer 99999999999
Call test_integer 1e272
Call test_integer 'AA'
Call test_integer '0'
Call test_integer '1.000-3i'
Call test_integer '1.000-3.3i'
Call test_integer '4j'
Call test_integer '2.00000000+0j'
Call test_integer '0j'
Call test_integer '333'
Call test_integer '-1-i'
Call test_integer '1+i'
Call test_integer '.00i'
Call test_integer 'j'
Call test_integer '0003-00.0j'
Exit

test_integer:
Parse Arg xx
Numeric Digits 1000
Parse Value parse_number(xx) With x imag
If imag<>0 Then Do
  Say left(xx,13) 'is not an integer (imaginary part is not zero)'
  Return
  End
Select
  When datatype(x)<>'NUM' Then
    Say left(xx,13) 'is not an integer (not even a number)'
  Otherwise Do
    If datatype(x,'W') Then
      Say left(xx,13) 'is an integer'
    Else
      Say left(xx,13) 'isn''t an integer'
    End
  End
Return
parse_number: Procedure
  Parse Upper Arg x
  x=translate(x,'I','J')
  If pos('I',x)>0 Then Do
    pi=verify(x,'+-','M')
    Select
      When pi>1 Then Do
        real=left(x,pi-1)
        imag=substr(x,pi)
        End
      When pi=0 Then Do
        real=0
        imag=x
        End
      Otherwise /*pi=1*/Do
        p2=verify(substr(x,2),'+-','M')
        If p2>0 Then Do
          real=left(x,p2)
          imag=substr(x,p2+1)
          End
        Else Do
          real=0
          imag=x
          End
        End
      End
    End
  Else Do
    real=x
    imag='0I'
    End
  pi=verify(imag,'+-','M')
  If pi=0 Then Do
    Parse Var imag imag_v 'I'
    imag_sign='+'
    End
  Else
    Parse Var imag imag_sign 2 imag_v 'I'
  If imag_v='' Then
    imag_v=1
  imag=imag_sign||imag_v

  Return real imag


/* Palindrome detection, in Jsish */
function isPalindrome(str:string, exact:boolean=true) {
  if (!exact) {
      str = str.toLowerCase().replace(/[^a-z0-9]/g, '');
  }
  return str === str.split('').reverse().join('');
}


using Base.Test
include("Palindrome_detection.jl")

# Simple test
@test palindrome("abcdcba")
@test !palindrome("abd")

# Test sets
@testset "palindromes" begin
    @test palindrome("aaaaa")
    @test palindrome("abcba")
    @test palindrome("1")
    @test palindrome("12321")
end

@testset "non-palindromes" begin
    @test !palindrome("abc")
    @test !palindrome("a11")
    @test !palindrome("012")
end


// version 1.1.3

fun isPalindrome(s: String) = (s == s.reversed())

fun main(args: Array<String>) {
    val testCases = listOf("racecar", "alice", "eertree", "david")
    for (testCase in testCases) {
        try {
            assert(isPalindrome(testCase)) { "$testCase is not a palindrome" }
        }
        catch (ae: AssertionError) {
            println(ae.message)
        }
    }
}


#include <boost/regex.hpp>
#include <fstream>
#include <iostream>
#include <vector>
#include <string>
#include <set>
#include <cstdlib>
#include <algorithm>
using namespace std ;

boost::regex e ( "\\s+" ) ;

int main( int argc , char *argv[ ] ) {
   ifstream infile( argv[ 1 ] ) ;
   vector<string> duplicates ;
   set<string> datestamps ; //for the datestamps
   if ( ! infile.is_open( ) ) {
      cerr << "Can't open file " << argv[ 1 ] << '\n' ;
      return 1 ;
   }
   int all_ok = 0  ;//all_ok for lines in the given pattern e
   int pattern_ok = 0 ; //overall field pattern of record is ok
   while ( infile ) {
      string eingabe ;
      getline( infile , eingabe ) ;
      boost::sregex_token_iterator i ( eingabe.begin( ), eingabe.end( ) , e , -1 ), j  ;//we tokenize on empty fields
      vector<string> fields( i, j ) ;
      if ( fields.size( ) == 49 ) //we expect 49 fields in a record
         pattern_ok++ ;
      else
         cout << "Format not ok!\n" ;
      if ( datestamps.insert( fields[ 0 ] ).second ) { //not duplicated
         int howoften = ( fields.size( ) - 1 ) / 2 ;//number of measurement
                                                    //devices and values
         for ( int n = 1 ; atoi( fields[ 2 * n ].c_str( ) ) >= 1 ; n++ ) {
            if ( n == howoften ) {
               all_ok++ ;
               break ;
            }
         }
      }
      else {
         duplicates.push_back( fields[ 0 ] ) ;//first field holds datestamp
      }
   }
   infile.close( ) ;
   cout << "The following " << duplicates.size() << " datestamps were duplicated:\n" ;
   copy( duplicates.begin( ) , duplicates.end( ) ,
         ostream_iterator<string>( cout , "\n" ) ) ;
   cout << all_ok << " records were complete and ok!\n" ;
   return 0 ;
}


class Numeric
  def to_i?
    self == self.to_i rescue false
   end
end

# Demo
ar = [25.000000, 24.999999, 25.000100, -2.1e120, -5e-2,  # Floats
      Float::NAN, Float::INFINITY,                       # more Floats
      2r, 2.5r,                                          # Rationals
      2+0i, 2+0.0i, 5-5i]                                # Complexes

ar.each{|num| puts "#{num} integer? #{num.to_i?}" }


sash[r7rs]> (integer? 1)
#t
sash[r7rs]> (integer? 2/3)
#f
sash[r7rs]> (integer? 4/2)
#t
sash[r7rs]> (integer? 1+3i)
#f
sash[r7rs]> (integer? 1+0i)
#t
sash[r7rs]> (exact? 3.0)
#f
sash[r7rs]> (integer? 3.0)
#t
sash[r7rs]> (integer? 3.5)
#f
sash[r7rs]> (integer? 1.23e3)
#t
sash[r7rs]> (integer? 1.23e1)
#f
sash[r7rs]> (integer? 1e120)
#t


V nodata = 0
V nodata_max = -1
[String] nodata_maxline
V tot_file = 0.0
V num_file = 0

:start:
L(line) File(:argv[1]).read().rtrim("\n").split("\n")
   V tot_line = 0.0
   V num_line = 0

   V field = line.split("\t")
   V date  = field[0]
   V data  = field[(1..).step(2)].map(f -> Float(f))
   V flags = field[(2..).step(2)].map(f -> Int(f))

   L(datum, flag) zip(data, flags)
      I flag < 1
         nodata++
      E
         I nodata_max == nodata & nodata > 0
            nodata_maxline.append(date)
         I nodata_max < nodata & nodata > 0
            nodata_max = nodata
            nodata_maxline = [date]
         nodata = 0
         tot_line += datum
         num_line++

   tot_file += tot_line
   num_file += num_line

   print(‘Line: #11  Reject: #2  Accept: #2  Line_tot: #6.3  Line_avg: #6.3’.format(
         date, data.len - num_line, num_line, tot_line, I (num_line > 0) {tot_line / num_line} E 0))

print()
print(‘File(s)  = #.’.format(:argv[1]))
print(‘Total    = #6.3’.format(tot_file))
print(‘Readings = #6’.format(num_file))
print(‘Average  = #6.3’.format(tot_file / num_file))
print("\nMaximum run(s) of #. consecutive false readings ends at line starting with date(s): #.".format(nodata_max, nodata_maxline.join(‘, ’)))


// Taken from the Lasso entry in Palindrome page
define isPalindrome(text::string) => {

    local(_text = string(#text)) // need to make copy to get rid of reference issues

    #_text -> replace(regexp(`(?:$|\W)+`), -ignorecase)

    local(reversed = string(#_text))
    #reversed -> reverse

    return #_text == #reversed
}

// The tests
describe(::isPalindrome) => {
    it(`throws an error when not passed a string`) => {
        expect->error =>{
            isPalindrome(43)
        }
    }

    it(`returns true if the string is the same forward and backwords`) => {
        expect(isPalindrome('abba'))
    }

    it(`returns false if the string is different forward and backwords`) => {
        expect(not isPalindrome('aab'))
    }

    it(`ignores spaces and punctuation`) => {
        expect(isPalindrome(`Madam, I'm Adam`))
    }
}

// Run the tests and get the summary
// (This normally isn't in the code as the test suite is run via command-line.)
lspec->stop


assert( ispalindrome("ABCBA") )
assert( ispalindrome("ABCDE") )


myFun[x_] := Block[{y},y = x^2; Assert[y > 5]; Sin[y]]
On[Assert];myFun[1.0]


/* NetRexx */

options replace format comments java crossref savelog symbols binary

import junit.framework.TestCase
import RCPalindrome

class RCTestAFunction public final extends TestCase

method setUp public
  return

method tearDown public
  return

method testIsPal public signals AssertionError

  assertTrue(RCPalindrome.isPal(Rexx 'abcba'))
  assertTrue(RCPalindrome.isPal(Rexx 'aa'))
  assertTrue(RCPalindrome.isPal(Rexx 'a'))
  assertTrue(RCPalindrome.isPal(Rexx ''))
  assertFalse(RCPalindrome.isPal(Rexx 'ab'))
  assertFalse(RCPalindrome.isPal(Rexx 'abcdba'))

  return

method except signals RuntimeException
  signal RuntimeException()

method main(args = String[]) public constant

  testResult = org.junit.runner.JUnitCore.runClasses([RCTestAFunction.class])

  secs = Rexx testResult.getRunTime / 1000.0

  if testResult.wasSuccessful then say 'Tests successful'
                              else say 'Tests failed'
  say '  failure count:' testResult.getFailureCount
  say '   ignore count:' testResult.getIgnoreCount
  say '      run count:' testResult.getRunCount
  say '       run time:' secs.format(null, 3)

  return


(defn parse-line [s]
  (let [[date & data-toks] (str/split s #"\s+")
        data-fields (map read-string data-toks)
        valid-date? (fn [s] (re-find #"\d{4}-\d{2}-\d{2}" s))
        valid-line? (and (valid-date? date)
                         (= 48 (count data-toks))
                         (every? number? data-fields))
        readings    (for [[v flag] (partition 2 data-fields)]
                      {:val v :flag flag})]
    (when (not valid-line?)
      (println "Malformed Line: " s))
    {:date date
     :no-missing-readings? (and (= 48 (count data-toks))
                                (every? pos? (map :flag readings)))}))

(defn analyze-file [path]
  (reduce (fn [m line]
            (let [{:keys [all-dates dupl-dates n-full-recs invalid-lines]} m
                  this-date (:date line)
                  dupl? (contains? all-dates this-date)
                  full? (:no-missing-readings? line)]
              (cond-> m
                dupl? (update-in [:dupl-dates]  conj this-date)
                full? (update-in [:n-full-recs] inc)
                true  (update-in [:all-dates]   conj this-date))))
          {:dupl-dates #{} :all-dates #{} :n-full-recs 0}
          (->> (slurp path)
               clojure.string/split-lines
               (map parse-line))))

(defn report-summary [path]
  (let [m (analyze-file path)]
    (println (format "%d unique dates" (count (:all-dates m))))
    (println (format "%d duplicated dates [%s]"
                     (count (:dupl-dates m))
                     (clojure.string/join " " (sort (:dupl-dates m)))))
    (println (format "%d lines with no missing data" (:n-full-recs m)))))


proc isNumberIntegral {x} {
    expr {$x == entier($x)}
}
# test with various kinds of numbers:
foreach x {1e100 3.14 7 1.000000000000001 1000000000000000000000 -22.7 -123.000} {
    puts [format "%s: %s" $x [expr {[isNumberIntegral $x] ? "yes" : "no"}]]
}


import "/big" for BigRat
import "/complex" for Complex
import "/rat" for Rat
import "/fmt" for Fmt

var tests1 = [25.000000, 24.999999, 25.000100]
var tests2 = ["-2.1e120"]
var tests3 = [-5e-2, 0/0, 1/0]
var tests4 = [Complex.fromString("5.0+0.0i"), Complex.fromString("5-5i")]
var tests5 = [Rat.new(24, 8), Rat.new(-5, 1), Rat.new(17, 2)]
var tests6 = tests1 + [-5e-2]

System.print("Using exact arithmetic:\n")
for (t in tests1) {
    Fmt.print("  $-9.6f is integer? $s", t, t.isInteger)
}
System.print()
for (t in tests2) {
    Fmt.print("  $-9s is integer? $s", t, BigRat.new(t, 1).isInteger)
}
for (t in tests3) {
    Fmt.print("  $-9.6f is integer? $s", t, t.isInteger)
}
System.print()
for (t in tests4) {
    Fmt.print("  $-9s is integer? $s", t, t.isRealInteger)
}
System.print()
for (t in tests5) {
    Fmt.print("  $-9s is integer? $s", t, t.isInteger)
}
System.print("\nWithin a tolerance of 0.00001:\n")
var tol = 0.00001
for (t in tests6) {
    var d = (t - t.round).abs
    Fmt.print("  $9.6f is integer? $s", t, d <= tol)
}


with Ada.Text_IO;            use Ada.Text_IO;
with Strings_Edit;           use Strings_Edit;
with Strings_Edit.Floats;    use Strings_Edit.Floats;
with Strings_Edit.Integers;  use Strings_Edit.Integers;

procedure Data_Munging is
   Syntax_Error : exception;
   type Gap_Data is record
      Count   : Natural := 0;
      Line    : Natural := 0;
      Pointer : Integer;
      Year    : Integer;
      Month   : Integer;
      Day     : Integer;
   end record;
   File    : File_Type;
   Max     : Gap_Data;
   This    : Gap_Data;
   Current : Gap_Data;
   Count   : Natural := 0;
   Sum     : Float   := 0.0;
begin
   Open (File, In_File, "readings.txt");
   loop
      declare
         Line    : constant String := Get_Line (File);
         Pointer : Integer := Line'First;
         Flag    : Integer;
         Data    : Float;
      begin
         Current.Line := Current.Line + 1;
         Get (Line, Pointer, SpaceAndTab);
         Get (Line, Pointer, Current.Year);
         Get (Line, Pointer, Current.Month);
         Get (Line, Pointer, Current.Day);
         while Pointer <= Line'Last loop
            Get (Line, Pointer, SpaceAndTab);
            Current.Pointer := Pointer;
            Get (Line, Pointer, Data);
            Get (Line, Pointer, SpaceAndTab);
            Get (Line, Pointer, Flag);
            if Flag < 0 then
               if This.Count = 0 then
                  This := Current;
               end if;
               This.Count := This.Count + 1;
            else
               if This.Count > 0 and then Max.Count < This.Count then
                  Max := This;
               end if;
               This.Count := 0;
               Count := Count + 1;
               Sum   := Sum + Data;
            end if;
         end loop;
      exception
         when End_Error =>
            raise Syntax_Error;
      end;
   end loop;
exception
   when End_Error =>
      Close (File);
      if This.Count > 0 and then Max.Count < This.Count then
         Max := This;
      end if;
      Put_Line ("Average " & Image (Sum / Float (Count)) & " over " & Image (Count));
      if Max.Count > 0 then
         Put ("Max. " & Image (Max.Count) & " false readings start at ");
         Put (Image (Max.Line) & ':' & Image (Max.Pointer) & " stamped ");
         Put_Line (Image (Max.Year) & Image (Max.Month) & Image (Max.Day));
      end if;
   when others =>
      Close (File);
      Put_Line ("Syntax error at " & Image (Current.Line) & ':' & Image (Max.Pointer));
end Data_Munging;


integer bads, count, max_bads;
file f;
list l;
real s;
text bad_day, worst_day;

f.stdin;

max_bads = count = bads = s = 0;

while (f.list(l, 0) ^ -1) {
    integer i;

    i = 2;
    while (i < 49) {
        if (0 < atoi(l[i])) {
            count += 1;
            s += atof(l[i - 1]);
            if (max_bads < bads) {
                max_bads = bads;
                worst_day = bad_day;
            }
            bads = 0;
        } else {
            if (!bads) {
                bad_day = l[0];
            }
            bads += 1;
        }
        i += 2;
    }
}

o_form("Averaged /d3/ over ~ readings.\n", s / count, count);
o_("Longest bad run ", max_bads, ", started ", worst_day, ".\n");


proc reversed(s: string): string =
  result = newString(s.len)
  for i, c in s:
    result[s.high - i] = c

proc isPalindrome(s: string): bool =
  s == reversed(s)

when isMainModule:
  assert(isPalindrome(""))
  assert(isPalindrome("a"))
  assert(isPalindrome("aa"))
  assert(not isPalindrome("baa"))
  assert(isPalindrome("baab"))
  assert(isPalindrome("ba_ab"))
  assert(not isPalindrome("ba_ ab"))
  assert(isPalindrome("ba _ ab"))
  assert(not isPalindrome("abab"))


ocaml unix.cma -I +oUnit oUnit.cma  palindrome.cmo  palindrome_tests.ml


test: [ "abcd" isPalindrome ]
test: ["abba" isPalindrome ]
test: [ "abcba" isPalindrome ]


# ptest.t
use strict;
use warnings;

use Test;

my %tests;
BEGIN {
    # plan tests before loading Palindrome.pm
    %tests = (
        'A man, a plan, a canal: Panama.'           => 1,
        'My dog has fleas'                          => 0,
        "Madam, I'm Adam."                          => 1,
        '1 on 1'                                    => 0,
        'In girum imus nocte et consumimur igni'    => 1,
        ''                                          => 1,
    );

    # plan 4 tests per string
    plan tests => (keys(%tests) * 4);
}

use Palindrome;

for my $key (keys %tests) {
    $_ = lc $key;  # convert to lowercase
    s/[\W_]//g;    # keep only alphanumeric characters

    my $expect = $tests{$key};
    my $note = ("\"$key\" should " . ($expect ? '' : 'not ') .
                "be a palindrome.");

    ok palindrome == $expect, 1, "palindrome: $note";
    ok palindrome_c == $expect, 1, "palindrome_c: $note";
    ok palindrome_r == $expect, 1, "palindrome_r: $note";
    ok palindrome_e == $expect, 1, "palindrome_e: $note";
}