WeixiangYan/CodeTransOcean huggingface dataset:
Task: World Cup group stage


C++: #include <algorithm>
#include <array>
#include <iomanip>
#include <iostream>
#include <sstream>

std::array<std::string, 6> games{ "12", "13", "14", "23", "24", "34" };
std::string results = "000000";

int fromBase3(std::string num) {
    int out = 0;
    for (auto c : num) {
        int d = c - '0';
        out = 3 * out + d;
    }
    return out;
}

std::string toBase3(int num) {
    std::stringstream ss;

    while (num > 0) {
        int rem = num % 3;
        num /= 3;
        ss << rem;
    }

    auto str = ss.str();
    std::reverse(str.begin(), str.end());
    return str;
}

bool nextResult() {
    if (results == "222222") {
        return false;
    }

    auto res = fromBase3(results);

    std::stringstream ss;
    ss << std::setw(6) << std::setfill('0') << toBase3(res + 1);
    results = ss.str();

    return true;
}

int main() {
    std::array<std::array<int, 10>, 4> points;
    for (auto &row : points) {
        std::fill(row.begin(), row.end(), 0);
    }

    do {
        std::array<int, 4> records {0, 0, 0, 0 };

        for (size_t i = 0; i < games.size(); i++) {
            switch (results[i]) {
            case '2':
                records[games[i][0] - '1'] += 3;
                break;
            case '1':
                records[games[i][0] - '1']++;
                records[games[i][1] - '1']++;
                break;
            case '0':
                records[games[i][1] - '1'] += 3;
                break;
            default:
                break;
            }
        }

        std::sort(records.begin(), records.end());
        for (size_t i = 0; i < records.size(); i++) {
            points[i][records[i]]++;
        }
    } while (nextResult());

    std::cout << "POINTS       0    1    2    3    4    5    6    7    8    9\n";
    std::cout << "-------------------------------------------------------------\n";
    std::array<std::string, 4> places{ "1st", "2nd", "3rd", "4th" };
    for (size_t i = 0; i < places.size(); i++) {
        std::cout << places[i] << " place";
        for (size_t j = 0; j < points[i].size(); j++) {
            std::cout << std::setw(5) << points[3 - i][j];
        }
        std::cout << '\n';
    }
    return 0;
}
Task: Almkvist-Giullera formula for pi


C++: #include <boost/multiprecision/cpp_dec_float.hpp>
#include <boost/multiprecision/gmp.hpp>
#include <iomanip>
#include <iostream>

namespace mp = boost::multiprecision;
using big_int = mp::mpz_int;
using big_float = mp::cpp_dec_float_100;
using rational = mp::mpq_rational;

big_int factorial(int n) {
    big_int result = 1;
    for (int i = 2; i <= n; ++i)
        result *= i;
    return result;
}


big_int almkvist_giullera(int n) {
    return factorial(6 * n) * 32 * (532 * n * n + 126 * n + 9) /
           (pow(factorial(n), 6) * 3);
}

int main() {
    std::cout << "n |                  Integer portion of nth term\n"
              << "------------------------------------------------\n";
    for (int n = 0; n < 10; ++n)
        std::cout << n << " | " << std::setw(44) << almkvist_giullera(n)
                  << '\n';

    big_float epsilon(pow(big_float(10), -70));
    big_float prev = 0, pi = 0;
    rational sum = 0;
    for (int n = 0;; ++n) {
        rational term(almkvist_giullera(n), pow(big_int(10), 6 * n + 3));
        sum += term;
        pi = sqrt(big_float(1 / sum));
        if (abs(pi - prev) < epsilon)
            break;
        prev = pi;
    }
    std::cout << "\nPi to 70 decimal places is:\n"
              << std::fixed << std::setprecision(70) << pi << '\n';
}
Task: Partition function P


C++: #include <chrono>
#include <iostream>
#include <vector>
#include <gmpxx.h>

using big_int = mpz_class;

big_int partitions(int n) {
    std::vector<big_int> p(n + 1);
    p[0] = 1;
    for (int i = 1; i <= n; ++i) {
        for (int k = 1;; ++k) {
            int j = (k * (3*k - 1))/2;
            if (j > i)
                break;
            if (k & 1)
                p[i] += p[i - j];
            else
                p[i] -= p[i - j];
            j = (k * (3*k + 1))/2;
            if (j > i)
                break;
            if (k & 1)
                p[i] += p[i - j];
            else
                p[i] -= p[i - j];
        }
    }
    return p[n];
}

int main() {
    auto start = std::chrono::steady_clock::now();
    auto result = partitions(6666);
    auto end = std::chrono::steady_clock::now();
    std::chrono::duration<double, std::milli> ms(end - start);
    std::cout << result << '\n';
    std::cout << "elapsed time: " << ms.count() << " milliseconds\n";
}
Task: Legendre prime counting function


C++: #include <cmath>
#include <iostream>
#include <vector>

std::vector<int> generate_primes(int limit) {
    std::vector<bool> sieve(limit >> 1, true);
    for (int p = 3, s = 9; s < limit; p += 2) {
        if (sieve[p >> 1]) {
            for (int q = s; q < limit; q += p << 1)
                sieve[q >> 1] = false;
        }
        s += (p + 1) << 2;
    }
    std::vector<int> primes;
    if (limit > 2)
        primes.push_back(2);
    for (int i = 1; i < sieve.size(); ++i) {
        if (sieve[i])
            primes.push_back((i << 1) + 1);
    }
    return primes;
}

class legendre_prime_counter {
public:
    explicit legendre_prime_counter(int limit);
    int prime_count(int n);
private:
    int phi(int x, int a);
    std::vector<int> primes;
};

legendre_prime_counter::legendre_prime_counter(int limit) :
    primes(generate_primes(static_cast<int>(std::sqrt(limit)))) {}

int legendre_prime_counter::prime_count(int n) {
    if (n < 2)
        return 0;
    int a = prime_count(static_cast<int>(std::sqrt(n)));
    return phi(n, a) + a - 1;
}

int legendre_prime_counter::phi(int x, int a) {
    if (a == 0)
        return x;
    if (a == 1)
        return x - (x >> 1);
    int pa = primes[a - 1];
    if (x <= pa)
        return 1;
    return phi(x, a - 1) - phi(x / pa, a - 1);
}

int main() {
    legendre_prime_counter counter(1000000000);
    for (int i = 0, n = 1; i < 10; ++i, n *= 10)
        std::cout << "10^" << i << "\t" << counter.prime_count(n) << '\n';
}
Task: 24 game






PHP: #!/usr/bin/env php
The 24 Game
 
Given any four digits in the range 1 to 9, which may have repetitions,
Using just the +, -, *, and / operators; and the possible use of
brackets, (), show how to make an answer of 24.
 
An answer of "q" will quit the game.
An answer of "!" will generate a new set of four digits.
Otherwise you are repeatedly asked for an expression until it evaluates to 24
 
Note: you cannot form multiple digit numbers from the supplied digits,
so an answer of 12+12 when given 1, 2, 2, and 1 would not be allowed.

<?php

while (true) {
    $numbers = make_numbers();

    for ($iteration_num = 1; ; $iteration_num++) {
        echo "Expresion $iteration_num: ";

        $entry = rtrim(fgets(STDIN));

        if ($entry === '!') break;
        if ($entry === 'q') exit;

        $result = play($numbers, $entry);

        if ($result === null) {
            echo "That's not valid\n";
            continue;
        }
        elseif ($result != 24) {
            echo "Sorry, that's $result\n";
            continue;
        }
        else {
            echo "That's right! 24!!\n";
            exit;
        }
    }
}

function make_numbers() {
    $numbers = array();

    echo "Your four digits: ";

    for ($i = 0; $i < 4; $i++) {
        $number = rand(1, 9);

        if (!isset($numbers[$number])) {
            $numbers[$number] = 0;
        }
        $numbers[$number]++;
        print "$number ";
    }

    print "\n";

    return $numbers;
}

function play($numbers, $expression) {
    $operator = true;
    for ($i = 0, $length = strlen($expression); $i < $length; $i++) {
        $character = $expression[$i];

        if (in_array($character, array('(', ')', ' ', "\t"))) continue;

        $operator = !$operator;

        if (!$operator) {
            if (!empty($numbers[$character])) {
                $numbers[$character]--;
                continue;
            }
            return;
        }
        elseif (!in_array($character, array('+', '-', '*', '/'))) {
            return;
        }
    }

    foreach ($numbers as $remaining) {
        if ($remaining > 0) {
            return;
        }
    }
    
    return eval("return $expression;");
}
?>
Task: Count occurrences of a substring






PHP: <?php
echo substr_count("the three truths", "th"), PHP_EOL; // prints "3"
echo substr_count("ababababab", "abab"), PHP_EOL; // prints "2"
Task: Fractal tree






PHP: <?php
header("Content-type: image/png");

$width = 512;
$height = 512;
$img = imagecreatetruecolor($width,$height);
$bg = imagecolorallocate($img,255,255,255);
imagefilledrectangle($img, 0, 0, $width, $width, $bg);

$depth = 8;
function drawTree($x1, $y1, $angle, $depth){
    
    global $img;
    
    if ($depth != 0){
        $x2 = $x1 + (int)(cos(deg2rad($angle)) * $depth * 10.0);
        $y2 = $y1 + (int)(sin(deg2rad($angle)) * $depth * 10.0);
        
        imageline($img, $x1, $y1, $x2, $y2, imagecolorallocate($img,0,0,0));
        
        drawTree($x2, $y2, $angle - 20, $depth - 1);
        drawTree($x2, $y2, $angle + 20, $depth - 1);
    }
}

drawTree($width/2, $height, -90, $depth);

imagepng($img);
imagedestroy($img);
?>
Task: Rock-paper-scissors






PHP: <?php
echo "<h1>" . "Choose: ROCK - PAPER - SCISSORS" . "</h1>";
echo "<h2>";
echo "";

$player = strtoupper( $_GET["moves"] );
$wins = [
    'ROCK' => 'SCISSORS',
    'PAPER' => 'ROCK',
    'SCISSORS' => 'PAPER'
  ];
$a_i = array_rand($wins);
echo "<br>";
echo "Player chooses " . "<i style=\"color:blue\">" . $player . "</i>";
echo "<br>";
echo "<br>" . "A.I chooses " . "<i style=\"color:red\">"  . $a_i . "</i>";

$results = "";
if ($player == $a_i){
$results = "Draw";
} else if($wins[$a_i] == $player ){
  $results = "A.I wins";
} else {
  $results = "Player wins";
}

echo "<br>" . $results;
?>
Task: Abbreviations, easy






PHP: 
$commands = 'Add ALTer  BAckup Bottom  CAppend Change SCHANGE  CInsert CLAst COMPress COpy
   COUnt COVerlay CURsor DELete CDelete Down DUPlicate Xedit EXPand EXTract Find
   NFind NFINDUp NFUp CFind FINdup FUp FOrward GET Help HEXType Input POWerinput
   Join SPlit SPLTJOIN  LOAD  Locate CLocate  LOWercase UPPercase  LPrefix MACRO
   MErge MODify MOve MSG Next Overlay PARSE PREServe PURge PUT PUTD  Query  QUIT
   READ  RECover REFRESH RENum REPeat  Replace CReplace  RESet  RESTore  RGTLEFT
   RIght LEft  SAVE  SET SHift SI  SORT  SOS  STAck STATus  TOP TRAnsfer Type Up';

$input = 'riG   rePEAT copies  put mo   rest    types   fup.    6       poweRin';
$expect = 'RIGHT REPEAT *error* PUT MOVE RESTORE *error* *error* *error* POWERINPUT';
$table = makeCommandTable($commands);
$table_keys = array_keys($table);

$inputTable = processInput($input);

foreach ($inputTable as $word) {
    $rs = searchCommandTable($word, $table);
    if ($rs) {
        $output[] = $rs;
    } else {
        $output[] = '*error*';
    }

}
echo 'Input: '. $input. PHP_EOL;
echo 'Output: '. implode(' ', $output). PHP_EOL;

function searchCommandTable($search, $table) {
    foreach ($table as $key => $value) {
        if ((strtoupper(substr($value['word'], 0, strlen($search))) === strtoupper($search)) && (strlen($search) >= $value['min_length'])) {
            return $key;
        }
    }
    return false;
}

function processInput($input) {
    $input = preg_replace('!\s+!', ' ', $input);
    $pieces = explode(' ', trim($input));
    return $pieces;
}

function makeCommandTable($commands) {
    $commands = preg_replace('!\s+!', ' ', $commands);
    $pieces = explode(' ', trim($commands));
    foreach ($pieces as $word) {
        $rs[strtoupper($word)] = ['word'=>$word, 'min_length' => preg_match_all("/[A-Z]/", $word)];
    }
    return $rs;
}
Task: Sorting algorithms_Stooge sort






PHP: function stoogeSort(&$arr, $i, $j)
{
	if($arr[$j] < $arr[$i])
	{
		list($arr[$j],$arr[$i]) = array($arr[$i], $arr[$j]);
	}
	if(($j - $i) > 1)
	{
		$t = ($j - $i + 1) / 3;
		stoogesort($arr, $i, $j - $t);
		stoogesort($arr, $i + $t, $j);
		stoogesort($arr, $i, $j - $t);
	}
}
Task: Sorting algorithms_Shell sort






PHP: function shellSort($arr)
{
	$inc = round(count($arr)/2);
	while($inc > 0)
	{
		for($i = $inc; $i < count($arr);$i++){
			$temp = $arr[$i];
			$j = $i;
			while($j >= $inc && $arr[$j-$inc] > $temp)
			{
				$arr[$j] = $arr[$j - $inc];
				$j -= $inc;
			}
			$arr[$j] = $temp;
		}
		$inc = round($inc/2.2);
	}
	return $arr;
}
Task: Trabb Pardo–Knuth algorithm






PHP: <?php



function f($n)
{
    return sqrt(abs($n)) + 5 * $n * $n * $n;
}

$sArray = [];
echo "Enter 11 numbers.\n";
for ($i = 0; $i <= 10; $i++) {
    echo $i + 1, " - Enter number: "; 
    array_push($sArray, (float)fgets(STDIN)); 
}
echo PHP_EOL;

$sArray = array_reverse($sArray);

foreach ($sArray as $s) {
    $r = f($s);
    echo "f(", $s, ") = ";
    if ($r > 400) 
        echo "overflow\n";
    else
        echo $r, PHP_EOL;
}
?>
Task: Odd word problem






PHP: $odd = function ($prev) use ( &$odd ) {
	$a = fgetc(STDIN);
	if (!ctype_alpha($a)) {
		$prev();
		fwrite(STDOUT, $a);
		return $a != '.';
	}
	$clos = function () use ($a , $prev) {
		fwrite(STDOUT, $a);
		$prev();
	};
	return $odd($clos);
};
$even = function () {
	while (true) {
		$c = fgetc(STDIN);
		fwrite(STDOUT, $c);
		if (!ctype_alpha($c)) {
			return $c != ".";
		}
	}
};
$prev = function(){};
$e = false;
while ($e ? $odd($prev) : $even()) {
	$e = !$e;
}
Task: Self-describing numbers






PHP: <?php

function is_describing($number) {
    foreach (str_split((int) $number) as $place => $value) {
        if (substr_count($number, $place) != $value) { 
            return false;
        }
    }    
    return true;
}

for ($i = 0; $i <= 50000000; $i += 10) {
    if (is_describing($i)) {
        echo $i . PHP_EOL;
    }
}

?>
Task: Loops_Infinite






PHP: while(1)
    echo "SPAM\n";
Task: Sattolo cycle






PHP: function sattoloCycle($items) {
   for ($i = 0; $i < count($items); $i++) {
        $j = floor((mt_rand() / mt_getrandmax()) * $i);
        $tmp = $items[$i];
        $items[$i] = $items[$j];
        $items[$j] = $tmp;
    } 
    return $items;
}
Task: Table creation_Postal addresses






PHP: <?php
$db = new SQLite3(':memory:');
$db->exec("
    CREATE TABLE address (
        addrID     INTEGER PRIMARY KEY AUTOINCREMENT,
        addrStreet TEXT NOT NULL,
        addrCity   TEXT NOT NULL,
        addrState  TEXT NOT NULL,
        addrZIP    TEXT NOT NULL
    )
");
?>
Task: Execute HQ9+






PHP: 
$accumulator = 0;
echo 'HQ9+: ';
$program = trim(fgets(STDIN));

foreach (str_split($program) as $chr) {
    switch ($chr) {
        case 'H':
        case 'h':
            printHelloWorld();
            break;
        case 'Q':
        case 'q':
            printSource($program);
            break;
        case '9':
            print99Bottles();
            break;
        case '+':
            $accumulator = incrementAccumulator($accumulator);
            break;
        default:
            printError($chr);
    }
}

function printHelloWorld() {
    echo 'Hello, world!'. PHP_EOL;
}

function printSource($program) {
    echo var_export($program, true) . PHP_EOL;
}

function print99Bottles() {
    $n = 99;
    while($n >= 1) {
        echo $n;
        echo ' Bottles of Beer on the Wall ';
        echo $n;
        echo ' bottles of beer, take one down pass it around ';
        echo $n-1;
        echo ' bottles of beer on the wall.'. PHP_EOL;
        $n--;
    }
}

function incrementAccumulator($accumulator) {
    return ++$accumulator;
}

function printError($chr) {
    echo "Invalid input: ". $chr;
}
Task: Deepcopy






PHP: <?php
class Foo
{
    public function __clone()
    {
        $this->child = clone $this->child;
    }
}

$object = new Foo;
$object->some_value = 1;
$object->child = new stdClass;
$object->child->some_value = 1;

$deepcopy = clone $object;
$deepcopy->some_value++;
$deepcopy->child->some_value++;

echo "Object contains {$object->some_value}, child contains {$object->child->some_value}\n",
     "Clone of object contains {$deepcopy->some_value}, child contains {$deepcopy->child->some_value}\n";
?>
Task: RPG attributes generator






PHP: <?php

$attributesTotal = 0;
$count = 0;

while($attributesTotal < 75 || $count < 2) {
    $attributes = [];
    
    foreach(range(0, 5) as $attribute) {
        $rolls = [];
        
        foreach(range(0, 3) as $roll) {
            $rolls[] = rand(1, 6);
        }
        
        sort($rolls);
        array_shift($rolls);
        
        $total = array_sum($rolls);
        
        if($total >= 15) {
            $count += 1;
        }
        
        $attributes[] = $total;
    }
    
    $attributesTotal = array_sum($attributes);
}

print_r($attributes);
Task: Longest increasing subsequence






PHP: <?php
class Node {
    public $val;
    public $back = NULL;
}

function lis($n) {
    $pileTops = array();

    foreach ($n as $x) {

        $low = 0; $high = count($pileTops)-1;
        while ($low <= $high) {
            $mid = (int)(($low + $high) / 2);
            if ($pileTops[$mid]->val >= $x)
                $high = $mid - 1;
            else
                $low = $mid + 1;
        }
        $i = $low;
        $node = new Node();
        $node->val = $x;
        if ($i != 0)
            $node->back = $pileTops[$i-1];
        $pileTops[$i] = $node;
    }
    $result = array();
    for ($node = count($pileTops) ? $pileTops[count($pileTops)-1] : NULL;
         $node != NULL; $node = $node->back)
        $result[] = $node->val;

    return array_reverse($result);
}

print_r(lis(array(3, 2, 6, 4, 5, 1)));
print_r(lis(array(0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15)));
?>
Task: Active Directory_Connect






PHP: <?php
$ldap = ldap_connect($hostname, $port);
$success = ldap_bind($ldap, $username, $password);
Task: Sorting algorithms_Strand sort






PHP: $lst = new SplDoublyLinkedList();
foreach (array(1,20,64,72,48,75,96,55,42,74) as $v)
    $lst->push($v);
foreach (strandSort($lst) as $v)
    echo "$v ";

function strandSort(SplDoublyLinkedList $lst) {
    $result = new SplDoublyLinkedList();
    while (!$lst->isEmpty()) {
        $sorted = new SplDoublyLinkedList();
        $remain = new SplDoublyLinkedList();
        $sorted->push($lst->shift());
        foreach ($lst as $item) {
            if ($sorted->top() <= $item) {
                $sorted->push($item);
            } else {
                $remain->push($item);
            }
        }
        $result = _merge($sorted, $result);
        $lst = $remain;
    }
    return $result;
}

function _merge(SplDoublyLinkedList $left, SplDoublyLinkedList $right) {
    $res = new SplDoublyLinkedList();
    while (!$left->isEmpty() && !$right->isEmpty()) {
        if ($left->bottom() <= $right->bottom()) {
            $res->push($left->shift());
        } else {
            $res->push($right->shift());
        }
    }
    foreach ($left as $v)  $res->push($v);
    foreach ($right as $v) $res->push($v);
    return $res;
}
Task: Update a configuration file






PHP: <?php

$conf = file_get_contents('update-conf-file.txt');

$conf = preg_replace('/^(needspeeling)(|\s*\S*)$/mi', '; $1', $conf);

$conf = preg_replace('/^;?\s*(seedsremoved)/mi', '$1', $conf);

$conf = preg_replace('/^(numberofbananas)(|\s*\S*)$/mi', '$1 1024', $conf);

if (preg_match('/^;?\s*(numberofstrawberries)/mi', $conf, $matches)) {
    $conf = preg_replace('/^(numberofstrawberries)(|\s*\S*)$/mi', '$1 62000', $conf);
} else {
    $conf .= 'NUMBEROFSTRAWBERRIES 62000' . PHP_EOL;
}

echo $conf;
Task: Straddling checkerboard






PHP: $key2val = ["A"=>"30", "B"=>"31", "C"=>"32", "D"=>"33", "E"=>"5", "F"=>"34", "G"=>"35",
        "H"=>"0", "I"=>"36", "J"=>"37", "K"=>"38", "L"=>"2", "M"=>"4", "."=>"78", "N"=>"39",
        "/"=>"79", "O"=>"1", "0"=>"790", "P"=>"70", "1"=>"791", "Q"=>"71", "2"=>"792",
        "R"=>"8", "3"=>"793", "S"=>"6", "4"=>"794", "T"=>"9", "5"=>"795", "U"=>"72",
        "6"=>"796", "V"=>"73", "7"=>"797", "W"=>"74", "8"=>"798", "X"=>"75", "9"=>"799",
        "Y"=>"76", "Z"=>"77"];
        
$val2key = array_flip($key2val);

function encode(string $s) : string  {
    global $key2val;
     
    $callback = function($c) use ($key2val) { return $key2val[$c] ?? ''; };

    return implode(array_map($callback, str_split(strtoupper($s))));
}
    
function decode(string $s) : string {
     global $val2key;

     $callback = function($c) use ($val2key) { return $val2key[$c] ?? ''; };
     
     preg_match_all('/79.|7.|3.|./', $s, $m);
     
     return implode(array_map($callback, $m[0]));
}   

function main($s) {
    $encoded = encode($s);
    echo $encoded;
    echo "\n";
    echo decode($encoded);    
}

main('One night-it was on the twentieth of March, 1888-I was returning');
Task: Permutations with repetitions






PHP: <?php
function permutate($values, $size, $offset) {
    $count = count($values);
    $array = array();
    for ($i = 0; $i < $size; $i++) {
        $selector = ($offset / pow($count,$i)) % $count;
        $array[$i] = $values[$selector];
    }
    return $array;
}

function permutations($values, $size) {
    $a = array();
    $c = pow(count($values), $size);
    for ($i = 0; $i<$c; $i++) {
        $a[$i] = permutate($values, $size, $i);        
    }
    return $a;
}

$permutations = permutations(['bat','fox','cow'], 2);
foreach ($permutations as $permutation) {
    echo join(',', $permutation)."\n";
}
Task: Send an unknown method call






PHP: <?php
class Example {
  function foo($x) {
    return 42 + $x;
  }
}

$example = new Example();

$name = 'foo';
echo $example->$name(5), "\n";        // prints "47"

echo call_user_func(array($example, $name), 5), "\n";
?>
Task: Ramer-Douglas-Peucker line simplification






PHP: function perpendicular_distance(array $pt, array $line) {

  $dx = $line[1][0] - $line[0][0];
  $dy = $line[1][1] - $line[0][1];
  $mag = sqrt($dx * $dx + $dy * $dy);
  if ($mag > 0) {
    $dx /= $mag;
    $dy /= $mag;
  }

  $pvx = $pt[0] - $line[0][0];
  $pvy = $pt[1] - $line[0][1];
  $pvdot = $dx * $pvx + $dy * $pvy;

  $dsx = $pvdot * $dx;
  $dsy = $pvdot * $dy;
  $ax = $pvx - $dsx;
  $ay = $pvy - $dsy;

  return sqrt($ax * $ax + $ay * $ay);
}

function ramer_douglas_peucker(array $points, $epsilon) {
  if (count($points) < 2) {
    throw new InvalidArgumentException('Not enough points to simplify');
  }

  $dmax = 0;
  $index = 0;
  $end = count($points) - 1;
  $start_end_line = [$points[0], $points[$end]];
  for ($i = 1; $i < $end; $i++) {
    $dist = perpendicular_distance($points[$i], $start_end_line);
    if ($dist > $dmax) {
      $index = $i;
      $dmax = $dist;
    }
  }

  if ($dmax > $epsilon) {
    $new_start = ramer_douglas_peucker(array_slice($points, 0, $index + 1), $epsilon);
    $new_end = ramer_douglas_peucker(array_slice($points, $index), $epsilon);
    array_pop($new_start);
    return array_merge($new_start, $new_end);
  }


  return [ $points[0], $points[$end]];
}

$polyline = [
  [0,0],
  [1,0.1],
  [2,-0.1],
  [3,5],
  [4,6],
  [5,7],
  [6,8.1],
  [7,9],
  [8,9],
  [9,9],
];

$result = ramer_douglas_peucker($polyline, 1.0);
print "Result:\n";
foreach ($result as $point) {
  print $point[0] . ',' . $point[1] . "\n";
}