Pike Back to the Win32 Shootout
Back to dada's perl lab

[The Original Shootout]   [NEWS]   [FAQ]   [Methodology]   [Platform Details]   [Acknowledgements]   [Scorecard]  
All Source For pike
Ackermann's Function
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: ackermann.pike,v 1.8 2001/07/08 19:59:15 doug Exp $
// http://www.bagley.org/~doug/shootout/

int Ack(int M, int N) {
  if (M == 0) return( N + 1 );
  if (N == 0) return( Ack(M - 1, 1) );
  return( Ack(M - 1, Ack(M, (N - 1))) );
}

int main(int argc, array(string) argv) {
  int N = (int)argv[-1] || 1;
  write("Ack(3,%d): %d\n", N, Ack(3, N));
}
Array Access
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: ary3.pike,v 1.1 2001/05/31 02:27:48 doug Exp $
// http://www.bagley.org/~doug/shootout/

void main(int argc, array(string) argv)
{
    int n = (int)argv[-1];
    if (n < 1) n = 1;

    array(int) x = allocate(n);
    array(int) y = allocate(n);

    for (int i; i<n; i++) {
    x[i] = i + 1;
    }
    for (int k; k<1000; k++) {
    for (int i=n-1; i>=0; i--) {
        y[i] += x[i];
    }
    }
    write("%d %d\n", y[0], y[-1]);
}
Count Lines/Words/Chars
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: wc.pike,v 1.4 2001/06/07 17:55:11 doug Exp $
// http://www.bagley.org/~doug/shootout/
// from Per Hedbor, optimized by David Hedbor

enum State { Outside, Inside };

void main() {
    int nl = 0, nw = 0, nc = 0; // line, word and character counters
    int sl; // Size of input

    State state = Outside; // Inside or outside word

    string buf;
    string rest="";
    array l;
    do {
    buf = replace(Stdio.stdin.read( 4196 ), "\t", " ");
    if(strlen(buf)) {
        nc += sizeof(buf);
        l = (rest+ buf) / "\n";
        nl += sizeof(l)-1;
        foreach(l[..sizeof(l)-2], rest) {
        nw += sizeof(rest / " " - ({""}));
        }
        if(sizeof(l)>1) {
        rest = l[-1];
        } //else rest="";
    } else {
        nw += sizeof(rest / " " - ({""}));
        break;
    }
    } while( 1 );
    write("%d %d %d\n", nl, nw, nc);
}
Echo Client/Server
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: echo.pike,v 1.2 2001/01/03 12:12:52 doug Exp $
// http://www.bagley.org/~doug/shootout/
// based on code from: Per Hedbor

#define DATA "Hello there sailor\n"

void echo_server(Stdio.Port p, int n) {
    Stdio.File f = p->accept();
    int tbytes;
    string q;
    while( (q = f->read( 8192,1  )) && strlen( q ) ) {
    tbytes += strlen(q);
    f->write( q );
    }
    write( "server processed %d bytes\n", tbytes );
}

void echo_client(int p, int n) {
    int i;
    Stdio.File f = Stdio.File();

    f->connect( "localhost", p );
    int s = strlen(DATA);
    for (i=0; i<n; i++) {
    f->write( DATA );
    if(  f->read( s ) != DATA ) {
        werror( "Transfer error at repetition "+i+"\n");
        _exit( 1 );
    }
    }
    f->close();
    _exit( 0 );
}

/* Fork is not really available in a threaded pike. Thus this hack. It
 * assumes the pike binary can be found in your path, and that you have
 * a /usr/bin/env
 */
void start_client( int p, int n )
{
    Process.create_process( ({ "e:/pike/7.2.239/bin/pike.exe", __FILE__,
                   (string)p, (string)n }) );
}

void main(int argc, array argv)
{
    if( argc < 3 )
    {
    int n = max((int)argv[-1],1);
    Stdio.Port p = Stdio.Port( 0 );
    int pno = (int)((p->query_address( )/" ")[1]);
    start_client( pno, n );
    echo_server( p, n );
    } else {
    echo_client( (int)argv[1], (int)argv[2] );
    }
    sleep(1);
}
Exception Mechanisms
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: except.pike,v 1.2 2000/12/05 16:04:06 doug Exp $
// http://www.bagley.org/~doug/shootout/
// from: Per Hedbor

// this version requires Pike 7.1

class HiException( mixed value ) { constant IsHi = 1; }
class LoException( mixed value ) { constant IsLo = 1; }

void some_function( int num )
{
    if( mixed e = catch(  hi_function( num ) ) )
    error( "We shouldn't get here (%s)", describe_error( e ) );
}
  
int HI, LO;

void hi_function(int num)
{
    if( mixed e = catch( lo_function( num ) ) )
    if( e->IsHi )
        HI++;
    else
        throw( e );
}
  
void lo_function(int num)
{
    if( mixed e = catch(  blowup(num) ) )
    if( e->IsLo )
        LO++;
    else
        throw( e );
}
  
  
void blowup(int num)
{
    if( num & 1 )
    throw( LoException(num) );
    else
    throw( HiException(num) );
}
  
void main(int argc, array argv)
{
    int num = (int)argv[-1];
    if( num < 1 )
    num = 1;
    while(num)
    some_function( num-- );
    write( "Exceptions: HI=%d / LO=%d\n" , HI, LO );
}
Fibonacci Numbers
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: fibo.pike,v 1.2 2000/12/24 19:10:50 doug Exp $
// http://www.bagley.org/~doug/shootout/

int
fib(int n) {
    if (n < 2) return(1);
    return( fib(n-2) + fib(n-1) );
}

void
main(int argc, array(string) argv) {
    int n = max((int)argv[-1], 1);
    write("%d\n", fib(n));
}

Hash (Associative Array) Access
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: hash.pike,v 1.2 2000/12/12 21:28:39 doug Exp $
// http://www.bagley.org/~doug/shootout/
// from: Martin Nilsson

void main(int argc, array(string) argv)
{
    int i, c = 0;
    int n = (int)argv[-1];
    if (n < 1) n = 1;
      
    mapping(string:int) X = ([]);
    
    for (i=1; i<=n; i++) {
    X[sprintf("%x", i)] = i;
    }
    for (i=n; i>0; i--) {
    if (X[(string)i]) c++;
    }
    write("%d\n", c);
}
Hashes, Part II
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: hash2.pike,v 1.2 2001/01/02 07:11:13 doug Exp $
// http://www.bagley.org/~doug/shootout/

void main(int argc, array(string) argv) {
    int n = (int)argv[-1];
    if (n < 1) n = 1;
      
    mapping(string:int) hash1 = ([]);
    mapping(string:int) hash2 = ([]);
    for (int i=0; i<10000; i++)
    hash1["foo_" + i] = i;
    for (int i=0; i<n; i++) {
    foreach (indices(hash1), string k) {
        hash2[k] += hash1[k];
    }
    }
    write("%d %d %d %d\n", hash1["foo_1"], hash1["foo_9999"],
      hash2["foo_1"], hash2["foo_9999"]);
}
Heapsort
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: heapsort.pike,v 1.9 2001/05/08 02:46:59 doug Exp $
// http://www.bagley.org/~doug/shootout/
// from: Fredrik Noring

#define IM 139968
#define IA   3877
#define IC  29573

int last = 42;

float
gen_random(float max) { return(max * (last = (last * IA + IC) % IM) / IM); }

void heapsort(int n, array(float) ra) {
    int l, j, ir, i;
    float rra;

    l = (n >> 1) + 1;
    ir = n;
    for (;;) {
        if (l > 1) {
            rra = ra[--l];
        } else {
            rra = ra[ir];
            ra[ir] = ra[1];
            if (--ir == 1) {
                ra[1] = rra;
                return;
            }
        }
        i = l;
        j = l << 1;
        while (j <= ir) {
            if (j < ir && ra[j] < ra[j+1]) { ++j; }
            if (rra < ra[j]) {
                ra[i] = ra[j];
                j += (i = j);
            } else {
                j = ir + 1;
            }
        }
        ra[i] = rra;
    }
}

void main(int argc, array(string) argv) {
    int N = (int)argv[-1] || 1;
    array(float) ary;
    int i;
    
    // create an array of N random floats
    ary = allocate(N+1);
    for (i=1; i<=N; i++) {
        ary[i] = gen_random(1.0);
    }

    heapsort(N, ary);

    write("%.10g\n", ary[N]);
}
Hello World
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: hello.pike,v 1.2 2001/06/18 01:01:47 doug Exp $
// http://www.bagley.org/~doug/shootout/

int main() { write("hello world\n"); }

List Operations
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: lists.pike,v 1.2 2000/12/05 16:04:06 doug Exp $
// http://www.bagley.org/~doug/shootout/
// from: Per Hedbor


#define SIZE 10000

#define TB(X) werror( "%s: %.2f\n", X, gauge {
#define TE()  })

int test_lists()
{
    mixed Li1, Li2, Li3;
    // create a list of integers from 1 to SIZE.
    Li1 = (string)indices(allocate(SIZE+1))[1..];
    // copy the list to Li2.
    Li2 = copy_value( Li1 );
    // remove each element from left side of Li2 and append to
    // the right side of Li3 (preserving order)
  
    Li3 = "";

    while( sizeof( Li2 ) )
    {
    Li3 += Li2[..0];
    Li2 = Li2[1..];
    }
    // Li2 is now empty.
    // Remove each element from right side of Li3 and append to right
    // side of Li2
    while( sizeof( Li3 ) )
    {
    Li2 += Li3[sizeof( Li3 )-1..];
    Li3 = Li3[..sizeof( Li3 )-2];
    }
    // Li2 is now reversed, and Li3 empty.
    // Reverse Li1 in place.
    Li1 = reverse( Li1 );
    if( Li1[0] != SIZE )
    return 0;
    // compare Li1 and Li2 for equality, and return the length of the list.
    if( equal( Li1, Li2 ) )
    return sizeof( Li1 );
    return 0;
}

void main(int argc, array argv)
{
    int result, num = (int)argv[-1];
    if( num <=  0 )
    num = 1;
    while( num-- )
    result = test_lists();
    write("%d\n", result );
}
Matrix Multiplication
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: matrix.pike,v 1.2 2001/01/02 07:24:21 doug Exp $
// http://www.bagley.org/~doug/shootout/
// from: Per Hedbor

int size = 30;

array(array(int))
mkmatrix(int rows, int cols) {
    array(array(int)) m = allocate(rows);
    int count = 1;
    for (int i=0; i<rows; i++) {
    array(int) row = allocate(cols);
    for (int j=0; j<cols; j++) {
        row[j] = count++;
    }
    m[i] = row;
    }
    return(m);
}

void
main(int argc, array(string) argv) {
    int n = (int)argv[-1];
    if (n < 1)
      n = 1;
    
    Math.Matrix m1 = Math.Matrix(mkmatrix(size, size));
    Math.Matrix m2 = Math.Matrix(mkmatrix(size, size));
    Math.Matrix mm;
    for( int i = n; i>0; i-- )
      mm = m1 * m2;
    array q = (array(array(int)))(array)mm;
    write( "%d %d %d %d\n", q[0][0], q[2][3], q[3][2], q[4][4] );
}
Method Calls
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: methcall.pike,v 1.3 2000/12/24 22:04:51 doug Exp $
// http://www.bagley.org/~doug/shootout/

class Toggle {
    int bool;

    object create (int start_state) {
    bool = start_state;
    }

    int value () {
    return(bool);
    }

    object activate () {
    bool = !bool;
    return(this_object());
    }
}

class NthToggle {
    inherit Toggle;

    int count_max, count;

    object create (int start_state, int max_counter) {
    ::create(start_state);
    count_max = max_counter;
    count = 0;
    }

    object activate () {
    if (++count >= count_max) {
        bool = !bool;
        count = 0;
    }
    return(this_object());
    }
}

void main(int argc, array(string) argv) {
    int n = (int)argv[-1];
    if (n < 1) n = 1;
      
    int val = 1;
    object toggle = Toggle(val);
    for (int i=0; i<n; i++) {
    val = toggle->activate()->value();
    }
    write((toggle->value()) ? "true\n" : "false\n");

    val = 1;
    object ntoggle = NthToggle(val, 3);
    for (int i=0; i<n; i++) {
    val = ntoggle->activate()->value();
    }
    write((ntoggle->value()) ? "true\n" : "false\n");
}


Nested Loops
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: nestedloop.pike,v 1.1 2000/12/30 21:42:57 doug Exp $
// http://www.bagley.org/~doug/shootout/

void main(int argc, array(string) argv) {
  int n = (int)argv[-1];
  if (n < 1) n = 1;
  int x=0;

  for (int a; a<n; a++)
      for (int b; b<n; b++)
      for (int c; c<n; c++)
          for (int d; d<n; d++)
          for (int e; e<n; e++)
              for (int f; f<n; f++)
              x++;

  write("%d\n", x);
}
Object Instantiation
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: objinst.pike,v 1.3 2000/12/24 22:04:57 doug Exp $
// http://www.bagley.org/~doug/shootout/

class Toggle {
    int bool;

    object create (int start_state) {
    bool = start_state;
    }

    int value () {
    return(bool);
    }

    object activate () {
    bool = !bool;
    return(this_object());
    }
}

class NthToggle {
    inherit Toggle;

    int count_max, count;

    object create (int start_state, int max_counter) {
    ::create(start_state);
    count_max = max_counter;
    count = 0;
    }

    object activate () {
    if (++count >= count_max) {
        bool = !bool;
        count = 0;
    }
    return(this_object());
    }
}

void main(int argc, array(string) argv) {
    int n = (int)argv[-1];
    if (n < 1) n = 1;
      
    object toggle = Toggle(1);
    for (int i=0; i<5; i++) {
    toggle->activate();
    write((toggle->value()) ? "true\n" : "false\n");
    }
    for (int i=0; i<n; i++) {
    object toggle = Toggle(1);
    }

    write("\n");

    object ntoggle = NthToggle(1, 3);
    for (int i=0; i<8; i++) {
    ntoggle->activate();
    write((ntoggle->value()) ? "true\n" : "false\n");
    }
    for (int i=0; i<n; i++) {
    object ntoggle = NthToggle(1, 3);
    }
}


Producer/Consumer Threads
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: prodcons.pike,v 1.3 2000/12/20 05:03:58 doug Exp $
// http://www.bagley.org/~doug/shootout/

inherit Thread.Condition: access;
inherit Thread.Mutex: mutex;
int data, consumed, produced, count;

void producer(int n) {
    for (int i=1; i<=n; i++) {
    object mtx = mutex::lock();
    while (count != 0) access::wait(mtx);
    data = i;
    count += 1;
    destruct(mtx);
    access::signal();
    produced += 1;
    }
}

void consumer(int n) {
    while (1) {
    object mtx = mutex::lock();
    while (count == 0) access::wait(mtx);
    int i = data;
    count -= 1;
    access::signal();
    destruct(mtx);
    consumed += 1;
    if (i == n) break;
    }
}

void main(int argc, array(string) argv) {
    int n = (int)argv[-1];
    if (n < 1) n = 1;
    data = consumed = produced = count = 0;
    thread_create(producer, n);
    consumer(n);
    write("%d %d\n", produced, consumed);
}
Random Number Generator
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: random.pike,v 1.13 2001/05/08 06:35:56 doug Exp $
// http://www.bagley.org/~doug/shootout/

int IM = 139968;
int IA = 3877;
int IC = 29573;

int last = 42;

float
gen_random(float max) { return(max * (last = (last * IA + IC) % IM) / IM); }

int
main(int argc, array(string) argv) {
    float result = 0;
    int N = (int)argv[-1] || 1;
    while (N--) {
    result = gen_random(100.0);
    }
    write("%.9f\n", result);
    return(0);
}

Regular Expression Matching
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: regexmatch.pike,v 1.2 2000/12/05 16:04:06 doug Exp $
// http://www.bagley.org/~doug/shootout/
// from: Fredrik Noring

constant area = "([0-9][0-9][0-9]|\\([0-9][0-9][0-9]\\))";
constant exch = "([0-9][0-9][0-9])";
constant last = "([0-9][0-9][0-9][0-9])";

void main(int argc, array(string) argv)
{
    Regexp r = Regexp("^[^0-9\\(]*"+area+" "+exch+"[ -]"+last+"[^0-9]*$");
    array(string) phones = Stdio.stdin->read()/"\n";
    int n = (int)argv[-1];
    int count = 0;
      
    while(n--)
    foreach(phones, string phone)
        if(array(string) parts = r->split(phone))
        if(n == 0)
            if(parts[0][0] == '(')
            write("%d: %s %s-%s\n", ++count, @parts);
            else
            write("%d: (%s) %s-%s\n", ++count, @parts);
}
Reverse a File
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: reversefile.pike,v 1.4 2001/05/14 01:03:20 doug Exp $
// http://www.bagley.org/~doug/shootout/
// from: Fredrik Noring

void main() { write((reverse(Stdio.stdin.read()/"\n")*"\n")[1..]+"\n"); }
Sieve of Erathostenes
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: sieve.pike,v 1.9 2001/05/06 04:37:45 doug Exp $
// http://www.bagley.org/~doug/shootout/
// from: Per Hedbor

void main(int argc, array(string) argv)
{
    array(int) flags;
    int i, k, count, num;
  
    num = (int)argv[-1];
    if (num < 1)
    num = 1;
      
    while (num--) {
    count = 0;
    flags = ({ 1 })*8193;
    for (i=2; i <= 8192; i++) {
        if (flags[i]) {
        for (k=i+i; k <= 8192; k+=i)
            flags[k] = 0;
        count++;
        }
    }
    }
    write("Count: %d\n", count);
}
Spell Checker
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: spellcheck.pike,v 1.5 2000/12/05 16:04:06 doug Exp $
// http://www.bagley.org/~doug/shootout/

void main() {
    array(string) a = Stdio.read_file("Usr.Dict.Words")/"\n";
    mapping dictionary = mkmapping(a, allocate(sizeof(a), 1));
    while (string word = Stdio.stdin.gets()) {
    if (!dictionary[word]) write("%s\n", word);
    }
}
Statistical Moments
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: moments.pike,v 1.6 2001/01/05 01:35:56 doug Exp $
// http://www.bagley.org/~doug/shootout/
// from: Fredrik Noring

class Moments
{
    int N;
    float median;
    float mean;
    float average_deviation;
    float standard_deviation;
    float variance;
    float skew;
    float kurtosis;
    
    void create(array(float) v)
    {
        float sum = `+(@v);
        N = sizeof(v);
        mean = sum / N;

        foreach(v, float i)
        {
            float deviation = i - mean;
            average_deviation += abs(deviation);
            variance += pow(deviation, 2);
            skew += pow(deviation, 3);
            kurtosis += pow(deviation, 4);
        }

        average_deviation /= N;
        variance /= (N - 1);
        standard_deviation = sqrt(variance);

        if (variance)
        {
            skew /= (N * variance * standard_deviation);
            kurtosis = kurtosis/(N * variance * variance) - 3.0;
        }

        sort(v);
        int mid = N/2;
        median = N % 2 ? v[mid] : (v[mid] + v[mid-1])/2;
    }
};

int main()
{
    array input = Stdio.stdin.read()/"\n";
    Moments m=Moments( (array(float)) input[..sizeof(input)-2] );

    write("n:                  %d\n", m->N);
    write("median:             %.6f\n", m->median);
    write("mean:               %.6f\n", m->mean);
    write("average_deviation:  %.6f\n", m->average_deviation);
    write("standard_deviation: %.6f\n", m->standard_deviation);
    write("variance:           %.6f\n", m->variance);
    write("skew:               %.6f\n", m->skew);
    write("kurtosis:           %.6f\n", m->kurtosis);
}
String Concatenation
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: strcat.pike,v 1.2 2001/05/16 13:32:03 doug Exp $
// http://www.bagley.org/~doug/shootout/
// from Per Hedbor

void main(int argc, array(string) argv) {
    int n = (int)argv[-1];
    if (n < 1) n = 1;
      
    String.Buffer str = String.Buffer();
    function f = str->add;
    for (int i=0; i<n; i++) {
    f("hello\n");
    }
    write("%d\n", strlen(str->get()));
}
Sum a Column of Integers
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: sumcol.pike,v 1.7 2000/12/05 16:04:07 doug Exp $
// http://www.bagley.org/~doug/shootout/
// from: Fredrik Noring

void
main() {
    int sum = 0;
    while(string line = Stdio.stdin.gets())
    sum += (int)line;
    write("%d\n", sum);
}
Word Frequency Count
#!/usr/local/bin/pike// -*- mode: pike -*-
// $Id: wordfreq.pike,v 1.3 2000/12/05 16:04:07 doug Exp $
// http://www.bagley.org/~doug/shootout/
// from: Fredrik Noring

void main()
{
    mapping(string:int) dictionary = ([]);
    string buffer = "";

    array(string) f = filter(map(enumerate(128),
                   lambda(int i)
                   {
                       return !('A' <= i && i <= 'Z' ||
                        'a' <= i && i <= 'z' ||
                        i == ' ') &&
                          sprintf("%c", i);
                   }), `!=, 0);
    array(string) t = allocate(sizeof(f), " ");

    for(;;)
    {
      string data =
          buffer + replace(lower_case(Stdio.stdin.read(4096)), f, t);
      
      if(!sizeof(data))
          break;
      
      array(string) words = data/" ";

      if(1 < sizeof(words) && sizeof(words[-1]))
          buffer = words[-1],
           words = words[..sizeof(words)-2];
      else
          buffer = "";

      foreach(words, string word)
          dictionary[word]++;
    }
    
    m_delete(dictionary, "");

    mapping(int:array(string)) revdictionary = ([]);
    array(string) words = indices(dictionary);
    array(int) freqs = values(dictionary);

    for(int i = 0; i < sizeof(dictionary); i++)
      revdictionary[freqs[i]] += ({ words[i] });

    freqs = sort(indices(revdictionary));
    for(int i = sizeof(freqs)-1; 0 <= i; i--)
    {
      int freq = freqs[i];
      words = sort(revdictionary[freq]);
      
      for(int j = sizeof(words)-1; 0 <= j; j--)
          write("%7d\t%s\n", freq, words[j]);
    }
}