PHP pack 9 bit int then 10 bit int - php

I'm trying to write a program in PHP which takes a list of 9 bit ints (0-511) and 10 bit ints (0-1023) and writes them as binary to a file then reads it back. for example:
$dataIn = array(array(275, 863), array(7, 93), array(510, 1010));
$binData = writeBin($dataIn);
$dataOut = readBin($binData);
var_dump($dataIn, $dataOut, $binData);
function writeBin($data) {
$bin = "";
foreach ($data as $d) {
// 9 bit 10 bit
$bin .= pack('SS', $d[0], $d[1]);
}
return $bin;
}
function readBin($bin) {
$bin = str_split($bin, 4);
$data = array();
foreach ($bin as $b) {
$up = unpack('SS', $b); // im only getting 275, 7 and 510 here
$data[] = $up;
}
return $data;
}
But how can i write these to the binary file/string so each section is 19 bits long, and then split it by the 19 bits when reading it back? So a file with 10 of these records in it should only be 190 bits

I solved this issue by writing my own class to write and read differing bit length numbers to binary:
$listLen = 10;
// get an array of 10 random 9 bit ints
$b9s = range(0, 511);
shuffle($b9s);
$b9s = array_slice($b9s, 0, $listLen);
// get an array of 10 random 10 bit ints
$b10s = range(0, 1023);
shuffle($b10s);
$b10s = array_slice($b10s, 0, $listLen);
//build array of input data
$dataIn = array();
for ($i = 0; $i < $listLen; $i++) {
$dataIn[] = array($b9s[$i], $b10s[$i]);
}
//-------
//initialise
$bitFormat = array(9, 10);
$BC = new BinConverter($bitFormat);
//pack
$BC->addData($dataIn);
$binData = $BC->getBin();
//unpack
$BC->setBin($binData);
$dataOut = $BC->getData();
var_dump($dataOut, $binData);
Class BinConverter {
private $bitFormat;
private $maxSectLen;
private $binary;
private $binData;
private $dataOffset;
// $bitFormat = list of bit lengths e.g. array(9, 10)
public function __construct($bitFormat) {
$this->setBitFormat($bitFormat);
$this->binary = "";
$this->binData = "";
$this->dataOffset = 0;
}
// $bitFormat = list of bit lengths e.g. array(9, 10)
public function setBitFormat($bitFormat) {
$bitFormat = array_merge($bitFormat);
$this->bitFormat = $bitFormat;
$this->maxSectLen = 0;
foreach ($this->bitFormat as $bpos => $bf) {
$this->bitFormat[$bpos] = (int) $bf;
$this->maxSectLen += $this->bitFormat[$bpos];
}
}
// $data = list of data sections to convert e.g. array(array(167, 89), array(62, 32), array(325, 975))
public function addData($data) {
foreach ($data as $d) {
$d = array_merge($d);
if (is_array($d) && count($d) != count($this->bitFormat)) {
throw new Exception("Invalid data section");
}
foreach ($d as $dpos => $dbit) {
$dbit = (int) $dbit;
$tbin = decbin($dbit);
if (strlen($tbin) > $this->bitFormat[$dpos]) {
throw new Exception("Data (".$dbit.") too big for ".$this->bitFormat[$dpos]." bit segment");
}
$this->binary .= $this->binPad($tbin, $this->bitFormat[$dpos]);
}
}
}
//returns binary representation of added data
public function getBin() {
$bin = "";
if ($this->binary) {
$bits = str_split($this->binary, 4);
foreach ($bits as $bpos => $bit) {
$bp = bindec($this->binPad($bit, 4));
$bin .= pack('C', $bp);
}
}
return $bin;
}
//$bin = string of binary data
public function setBin($bin) {
if (!is_string($bin)) {
throw new Exception("Invalid binary format");
}
$bdata = "";
foreach (str_split($bin) as $b) {
$unpacked = unpack('C', $b);
$binbit = $this->binPad(decbin($unpacked[1]), 4);
$bdata .= $binbit;
}
$this->binData = $bdata;
}
//returns unpacked data in the current bit format
public function getData() {
$data = array();
$binlen = strlen($this->binData);
if ($binlen) {
$bdata = $this->binData;
$overflow = $binlen % $this->maxSectLen % 4;
$lastbit = substr($bdata, -4);
$overflowBit = substr($lastbit, 0, $overflow);
$binbit = substr($lastbit, $overflow);
$bdata = substr($bdata, 0, -4) . $binbit;
$tdata = str_split($bdata, $this->maxSectLen);
foreach ($tdata as $d) {
if (strlen($d) != $this->maxSectLen) {
throw new Exception("Invalid binary format");
}
$offset = 0;
$ds = array();
foreach ($this->bitFormat as $bf) {
$ds[] = bindec(substr($d, $offset, $bf));
$offset += $bf;
}
$data[] = $ds;
}
}
return $data;
}
//returns unpacked data in the current bit format for (int) $ni number of sections
public function getNextSection($ni = null) {
$data = array();
$binlen = strlen($this->binData);
if ($binlen) {
$n = $ni;
if ($n === null) {
$n = 1;
}
$glen = $n*$this->maxSectLen;
$bdata = substr($this->binData, $this->dataOffset, $glen);
if (strlen($bdata) != $glen) {
throw new Exception("Invalid data format used");
}
$this->dataOffset += $glen;
if ($this->dataOffset+4 > $binlen) {
$overflow = $binlen - $this->dataOffset;
$lastbit = substr($this->binData, -4);
$overflowBit = substr($lastbit, 0, $overflow);
$binbit = substr($lastbit, $overflow);
$bdata = substr($bdata, 0, -(4-$overflow)) . $binbit;
}
$tdata = str_split($bdata, $this->maxSectLen);
foreach ($tdata as $d) {
if (strlen($d) != $this->maxSectLen) {
throw new Exception("Invalid binary format");
}
$offset = 0;
$ds = array();
foreach ($this->bitFormat as $bf) {
$ds[] = bindec(substr($d, $offset, $bf));
$offset += $bf;
}
$data[] = $ds;
}
if ($ni === null) {
return $data[0];
}
}
return $data;
}
private function binPad($var, $a) {
return str_pad($var, $a, '0', STR_PAD_LEFT);
}
}
and an example of how to use multiple bit formats in one file:
$listLen1 = rand(1, 20);
// get an array of 10 random 9 bit ints
$b9s = range(0, 511);
shuffle($b9s);
$b9s = array_slice($b9s, 0, $listLen1);
// get an array of 10 random 10 bit ints
$b10s = range(0, 1023);
shuffle($b10s);
$b10s = array_slice($b10s, 0, $listLen1);
//build array of input data
$dataIn1 = array();
for ($i = 0; $i < $listLen1; $i++) {
$dataIn1[] = array($b9s[$i], $b10s[$i]);
}
$listLen2 = rand(1, 20);
// get an array of 10 random 16 bit ints
$b16s = range(0, 65535);
shuffle($b16s);
$b16s = array_slice($b16s, 0, $listLen2);
// get an array of 10 random 8 bit ints
$b8s = range(0, 255);
shuffle($b8s);
$b8s = array_slice($b8s, 0, $listLen2);
// get an array of 10 random 14 bit ints
$b14s = range(0, 16383);
shuffle($b14s);
$b14s = array_slice($b14s, 0, $listLen2);
$dataIn2 = array();
for ($i = 0; $i < $listLen2; $i++) {
$dataIn2[] = array($b16s[$i], $b8s[$i], $b14s[$i]);
}
//-------
$file = './binfile.bf';
//initialise
$bitFormat1 = array(9, 10);
$bitFormat2 = array(16, 8, 14);
$BC = new BinConvert($bitFormat1);
//pack
$BC->addData($dataIn1);
$BC->setBitFormat($bitFormat2);
$BC->addData($dataIn2);
$binData = $BC->getBin();
file_put_contents($file,$binData);
//unpack
$binData = file_get_contents($file);
$BC->setBin($binData);
$BC->setBitFormat($bitFormat1);
$dataOut1 = $BC->getNextSection($listLen1);
$BC->setBitFormat($bitFormat2);
$dataOut2 = $BC->getNextSection($listLen2);
var_dump($dataOut1, $dataOut2, $binData);

Related

PHP - How to create all possibility from a string

Here, there is a example string "XjYAKpR" .. how to create all new string possibility with that string ??
I've tried before
function containAllRots($s, $arr) {
$n = strlen($s);
$a = array();
for ($i = 0; $i < $n ; $i++) {
$rotated = rotate(str_split($s), $i);
$a[] = $rotated;
}
print_r($a);die();
if (array_diff($arr, $a)) {
return True;
}
else
{
return False;
}
}
I make 2 function rotate and generate
function rotate($l, $n) {
$b = $l[$n];
$sisa = array_values(array_diff($l, array($b)));
for ($i = 0; $i < count($sisa) ; $i++) {
$random[] = generate($sisa, $b);
}
print_r($random);die();
$hasil = $l[$n] . implode("",$random);
return $hasil;
}
function generate($sisa, $b) {
$string = implode("",$sisa);
$length = count($sisa);
$size = strlen($string);
$str = '';
for( $i = 0; $i < $length; $i++ ) {
$str .= $string[ rand( 0, $size - 1 ) ];
}
Here there is a pair of functions that lets you calculate a permutation set
(no repetitions are taken in account)
function extends_permutation($char, $perm) {
$result = [];
$times = count($perm);
for ($i=0; $i<$times; $i++) {
$temp = $perm;
array_splice($temp, $i, 0, $char);
array_push($result, $temp);
}
array_push($result, array_merge($perm, [$char]));
return $result;
}
function extends_set_of_permutations($char, $set) {
$step = [];
foreach ($set as $perm) {
$step = array_merge($step, extends_permutation($char, $perm));
}
return $step;
}
you can use them to generate the required set of permutations. Something like this:
$seed = "XjYAKpR";
// the first set of permutations contains only the
// possible permutation of a one char string (1)
$result_set = [[$seed[0]]];
$rest = str_split(substr($seed,1));
foreach($rest as $char) {
$result_set = extends_set_of_permutations($char, $result_set);
}
$result_set = array_map('implode', $result_set);
sort($result_set);
At the end of the execution you will have the 5040 permutations generated by your string in the result_set array (sorted in alphabetical order).
Add a char and you will have more than 40000 results.
The functions are quite naive in implementation and naming, both aspects can be improved.

Symfony 2.8.8 dump function php7.1 not working

Recently I've upgraded my php to 7.1 and symfony to 2.8 and everything works ok but dump function, when I try to use it I get:
Notice: A non well formed numeric value encountered
500 Internal Server Error - ContextErrorException
in vendor/symfony/symfony/src/Symfony/Component/VarDumper/Cloner/VarCloner.php at line 298 -
}
}
self::$hashMask ^= hexdec(substr(spl_object_hash($obj), self::$hashOffset, PHP_INT_SIZE));
}
}
I do not know if it's something related to php configuration or what.
UPDATE it seems to be fixed on Symfony 2.8.10.
Previous answer:
Well, I have found a non pretty nice answer, but it works, so what I've done is copying the class VarCloner.php from Symfony 3.1.3 and changing it on my symfony 2.8, and that worked! So here is the class, I also paste here the one that I tried.
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien#symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\VarDumper\Cloner;
/**
* #author Nicolas Grekas <p#tchwork.com>
*/
class VarCloner extends AbstractCloner
{
private static $hashMask = 0;
private static $hashOffset = 0;
/**
* {#inheritdoc}
*/
protected function doClone($var)
{
$useExt = $this->useExt;
$i = 0; // Current iteration position in $queue
$len = 1; // Length of $queue
$pos = 0; // Number of cloned items past the first level
$refsCounter = 0; // Hard references counter
$queue = array(array($var)); // This breadth-first queue is the return value
$arrayRefs = array(); // Map of queue indexes to stub array objects
$hardRefs = array(); // Map of original zval hashes to stub objects
$objRefs = array(); // Map of original object handles to their stub object couterpart
$resRefs = array(); // Map of original resource handles to their stub object couterpart
$values = array(); // Map of stub objects' hashes to original values
$maxItems = $this->maxItems;
$maxString = $this->maxString;
$cookie = (object) array(); // Unique object used to detect hard references
$gid = uniqid(mt_rand(), true); // Unique string used to detect the special $GLOBALS variable
$a = null; // Array cast for nested structures
$stub = null; // Stub capturing the main properties of an original item value
// or null if the original value is used directly
$zval = array( // Main properties of the current value
'type' => null,
'zval_isref' => null,
'zval_hash' => null,
'array_count' => null,
'object_class' => null,
'object_handle' => null,
'resource_type' => null,
);
if (!self::$hashMask) {
self::initHashMask();
}
$hashMask = self::$hashMask;
$hashOffset = self::$hashOffset;
for ($i = 0; $i < $len; ++$i) {
$indexed = true; // Whether the currently iterated array is numerically indexed or not
$j = -1; // Position in the currently iterated array
$fromObjCast = array_keys($queue[$i]);
$fromObjCast = array_keys(array_flip($fromObjCast)) !== $fromObjCast;
$refs = $vals = $fromObjCast ? array_values($queue[$i]) : $queue[$i];
foreach ($queue[$i] as $k => $v) {
// $k is the original key
// $v is the original value or a stub object in case of hard references
if ($k !== ++$j) {
$indexed = false;
}
if ($fromObjCast) {
$k = $j;
}
if ($useExt) {
$zval = symfony_zval_info($k, $refs);
} else {
$refs[$k] = $cookie;
if ($zval['zval_isref'] = $vals[$k] === $cookie) {
$zval['zval_hash'] = $v instanceof Stub ? spl_object_hash($v) : null;
}
$zval['type'] = gettype($v);
}
if ($zval['zval_isref']) {
$vals[$k] = &$stub; // Break hard references to make $queue completely
unset($stub); // independent from the original structure
if (isset($hardRefs[$zval['zval_hash']])) {
$vals[$k] = $useExt ? ($v = $hardRefs[$zval['zval_hash']]) : ($refs[$k] = $v);
if ($v->value instanceof Stub && (Stub::TYPE_OBJECT === $v->value->type || Stub::TYPE_RESOURCE === $v->value->type)) {
++$v->value->refCount;
}
++$v->refCount;
continue;
}
}
// Create $stub when the original value $v can not be used directly
// If $v is a nested structure, put that structure in array $a
switch ($zval['type']) {
case 'string':
if (isset($v[0]) && !preg_match('//u', $v)) {
$stub = new Stub();
$stub->type = Stub::TYPE_STRING;
$stub->class = Stub::STRING_BINARY;
if (0 <= $maxString && 0 < $cut = strlen($v) - $maxString) {
$stub->cut = $cut;
$stub->value = substr($v, 0, -$cut);
} else {
$stub->value = $v;
}
} elseif (0 <= $maxString && isset($v[1 + ($maxString >> 2)]) && 0 < $cut = mb_strlen($v, 'UTF-8') - $maxString) {
$stub = new Stub();
$stub->type = Stub::TYPE_STRING;
$stub->class = Stub::STRING_UTF8;
$stub->cut = $cut;
$stub->value = mb_substr($v, 0, $maxString, 'UTF-8');
}
break;
case 'integer':
break;
case 'array':
if ($v) {
$stub = $arrayRefs[$len] = new Stub();
$stub->type = Stub::TYPE_ARRAY;
$stub->class = Stub::ARRAY_ASSOC;
// Copies of $GLOBALS have very strange behavior,
// let's detect them with some black magic
$a = $v;
$a[$gid] = true;
// Happens with copies of $GLOBALS
if (isset($v[$gid])) {
unset($v[$gid]);
$a = array();
foreach ($v as $gk => &$gv) {
$a[$gk] = &$gv;
}
} else {
$a = $v;
}
$stub->value = $zval['array_count'] ?: count($a);
}
break;
case 'object':
if (empty($objRefs[$h = $zval['object_handle'] ?: ($hashMask ^ hexdec(substr(spl_object_hash($v), $hashOffset, PHP_INT_SIZE)))])) {
$stub = new Stub();
$stub->type = Stub::TYPE_OBJECT;
$stub->class = $zval['object_class'] ?: get_class($v);
$stub->value = $v;
$stub->handle = $h;
$a = $this->castObject($stub, 0 < $i);
if ($v !== $stub->value) {
if (Stub::TYPE_OBJECT !== $stub->type || null === $stub->value) {
break;
}
if ($useExt) {
$zval['type'] = $stub->value;
$zval = symfony_zval_info('type', $zval);
$h = $zval['object_handle'];
} else {
$h = $hashMask ^ hexdec(substr(spl_object_hash($stub->value), $hashOffset, PHP_INT_SIZE));
}
$stub->handle = $h;
}
$stub->value = null;
if (0 <= $maxItems && $maxItems <= $pos) {
$stub->cut = count($a);
$a = null;
}
}
if (empty($objRefs[$h])) {
$objRefs[$h] = $stub;
} else {
$stub = $objRefs[$h];
++$stub->refCount;
$a = null;
}
break;
case 'resource':
case 'unknown type':
if (empty($resRefs[$h = (int) $v])) {
$stub = new Stub();
$stub->type = Stub::TYPE_RESOURCE;
$stub->class = $zval['resource_type'] ?: get_resource_type($v);
$stub->value = $v;
$stub->handle = $h;
$a = $this->castResource($stub, 0 < $i);
$stub->value = null;
if (0 <= $maxItems && $maxItems <= $pos) {
$stub->cut = count($a);
$a = null;
}
}
if (empty($resRefs[$h])) {
$resRefs[$h] = $stub;
} else {
$stub = $resRefs[$h];
++$stub->refCount;
$a = null;
}
break;
}
if (isset($stub)) {
if ($zval['zval_isref']) {
if ($useExt) {
$vals[$k] = $hardRefs[$zval['zval_hash']] = $v = new Stub();
$v->value = $stub;
} else {
$refs[$k] = new Stub();
$refs[$k]->value = $stub;
$h = spl_object_hash($refs[$k]);
$vals[$k] = $hardRefs[$h] = &$refs[$k];
$values[$h] = $v;
}
$vals[$k]->handle = ++$refsCounter;
} else {
$vals[$k] = $stub;
}
if ($a) {
if ($i && 0 <= $maxItems) {
$k = count($a);
if ($pos < $maxItems) {
if ($maxItems < $pos += $k) {
$a = array_slice($a, 0, $maxItems - $pos);
if ($stub->cut >= 0) {
$stub->cut += $pos - $maxItems;
}
}
} else {
if ($stub->cut >= 0) {
$stub->cut += $k;
}
$stub = $a = null;
unset($arrayRefs[$len]);
continue;
}
}
$queue[$len] = $a;
$stub->position = $len++;
}
$stub = $a = null;
} elseif ($zval['zval_isref']) {
if ($useExt) {
$vals[$k] = $hardRefs[$zval['zval_hash']] = new Stub();
$vals[$k]->value = $v;
} else {
$refs[$k] = $vals[$k] = new Stub();
$refs[$k]->value = $v;
$h = spl_object_hash($refs[$k]);
$hardRefs[$h] = &$refs[$k];
$values[$h] = $v;
}
$vals[$k]->handle = ++$refsCounter;
}
}
if ($fromObjCast) {
$refs = $vals;
$vals = array();
$j = -1;
foreach ($queue[$i] as $k => $v) {
foreach (array($k => $v) as $a => $v) {
}
if ($a !== $k) {
$vals = (object) $vals;
$vals->{$k} = $refs[++$j];
$vals = (array) $vals;
} else {
$vals[$k] = $refs[++$j];
}
}
}
$queue[$i] = $vals;
if (isset($arrayRefs[$i])) {
if ($indexed) {
$arrayRefs[$i]->class = Stub::ARRAY_INDEXED;
}
unset($arrayRefs[$i]);
}
}
foreach ($values as $h => $v) {
$hardRefs[$h] = $v;
}
return $queue;
}
private static function initHashMask()
{
$obj = (object) array();
self::$hashOffset = 16 - PHP_INT_SIZE;
self::$hashMask = -1;
if (defined('HHVM_VERSION')) {
self::$hashOffset += 16;
} else {
// check if we are nested in an output buffering handler to prevent a fatal error with ob_start() below
$obFuncs = array('ob_clean', 'ob_end_clean', 'ob_flush', 'ob_end_flush', 'ob_get_contents', 'ob_get_flush');
foreach (debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) as $frame) {
if (isset($frame['function'][0]) && !isset($frame['class']) && 'o' === $frame['function'][0] && in_array($frame['function'], $obFuncs)) {
$frame['line'] = 0;
break;
}
}
if (!empty($frame['line'])) {
ob_start();
debug_zval_dump($obj);
self::$hashMask = (int) substr(ob_get_clean(), 17);
}
}
self::$hashMask ^= hexdec(substr(spl_object_hash($obj), self::$hashOffset, PHP_INT_SIZE));
}
}
paste it into YourProject/vendor/symfony/symfony/src/Symfony/Component/VarDumper/Cloner/VarCloner.php
so, if someone find a better option, please give it to us! Thanks!!

String compression in php

Here is my input
aaaabbaaaababbbcccccccccccc
And this is my expected output
a4b2a4b1a1b3c12
I tried like doing foreach and then concating the count of values. It seems like brutforcing. Is there any way to do it efficiently in php .
Help pls
You can use regular expression to get the result
preg_match_all('/(.)\1*/', $str, $m, PREG_SET_ORDER);
$m = array_map(function($i) { return $i[1] . strlen($i[0]); } , $m);
echo implode('', $m); // a4b2a4b1a1b3c12
demo
Here's an example of how to do it with a few for loops (encoding and decoding):
$input = 'aaaabbaaaababbbcccccccccccc';
$encoded = SillyEncoding::encode($input);
$decoded = SillyEncoding::decode($encoded);
echo "input = \t", var_export($input, true), "\n";
echo "encoded = \t", var_export($encoded, true), "\n";
echo "decoded = \t", var_export($decoded, true), "\n";
Output:
input = 'aaaabbaaaababbbcccccccccccc'
encoded = 'a4b2a4b1a1b3c12'
decoded = 'aaaabbaaaababbbcccccccccccc'
The SillyEncoding class:
class SillyEncoding
{
private static $digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
static function encode($string)
{
$output = '';
if (strlen($string) > 0) {
$count = 0;
$char = $string[0];
for ($i = 0; isset($string[$i]); ++$i) {
if (isset(self::$digits[$string[$i]])) {
throw new \InvalidArgumentException(sprintf('The input string must not contain a digit at offset %d, got "%s"', $i, $string[$i]));
}
if ($string[$i] === $char) {
++$count;
} else {
$output .= "{$char}{$count}";
$count = 1;
$char = $string[$i];
}
if (!isset($string[$i + 1])) {
$output .= "{$char}{$count}";
}
}
}
return $output;
}
static function decode($string)
{
$output = '';
$length = strlen($string);
if ($length > 0) {
$char = $string[0];
$count = null;
if ($length < 2) {
throw new \InvalidArgumentException(sprintf('Input string must be empty or at least 2 bytes long, got %d bytes', $length));
}
if (isset(self::$digits[$string[0]])) {
throw new \InvalidArgumentException(sprintf('Input string must not start with a digit, got "%s"', $string[0]));
}
for ($i = 1; isset($string[$i]); ++$i) {
$isDigit = isset(self::$digits[$string[$i]]);
if ($isDigit) {
$count .= $string[$i];
}
if (!$isDigit || !isset($string[$i + 1])) {
if (null === $count) {
throw new \InvalidArgumentException(sprintf('Expected a digit at offset %d, got "%s"', $i, $string[$i]));
}
$count = (int) $count;
for ($j = 0; $j < $count; ++$j) {
$output .= $char;
}
$char = $string[$i];
$count = null;
}
}
}
return $output;
}
}
A few things to note:
this isn't an efficient compression algorithm - it might reduce the size if there are many repeated characters, but if you feed it "normal" text the output will be about twice the size of the input
the input cannot contain any digits whatsoever (OP: "the input will be strictly alphabets")
$str = str_split('aaaabbaaaababbbcccccccccccc');
$count = 0;
$a=$result=$b='';
for ($i=0; $i <= count($str); $i++) {
if($a==$str[$i]){
$count++;
$result = $a.$count;
} else{
if ($count > 0) {
$b .= $result;
}
$count = 1;
$a = $str[$i];
$result = $a.$count;
}
}
print_r($b);
See result

php - permutation - possible number

already look around but cant find what i want for PHP.
just say i have a number : 1234 ( can be splitted first into array )
and i want to get how many number combination possible for 2 digits, 3 digits , and 4 digits
for example :
possible 4 digits will be :
1234,1243,1324,1342, and so on. ( i dont know how many more )
possible 2 digits will be :
12,13,14,21,23,24,31,32,34,41,42,43
the closest one i get is :
$p = permutate(array('1','2','3','4'));
$result = array();
foreach($p as $perm) {
$result[]=join("",$perm);
}
$result = array_unique($result);
print join("|", $result);
function permutate($elements, $perm = array(), &$permArray = array()){
if(empty($elements)){
array_push($permArray,$perm); return;
}
for($i=0;$i<=count($elements)-1;$i++){
array_push($perm,$elements[$i]);
$tmp = $elements; array_splice($tmp,$i,1);
permutate($tmp,$perm,$permArray);
array_pop($perm);
}
return $permArray;
}
but how can i edit this so i can display for 3 and 2 digits ?
Thanks
i got what i want
it's from #mudasobwa link. and i edit to what i want.
<?php
$in = array(1,2,3,4,5,6);
$te = power_perms($in);
// print_r($te);
$thou=0;
$hun =0;
$pu = 0;
for($i=0;$i<count($te);$i++)
{
$jm = count($te[$i]);
for($j=0;$j<$jm;$j++)
{
$hsl[$i] = $hsl[$i] . $te[$i][$j];
}
if($hsl[$i] >=100 && $hsl[$i] < 1000 )
{
$ratus[$hun] = intval($hsl[$i]);
$hun = $hun + 1;
}
if($hsl[$i] <100 && $hsl[$i] >=10)
{
$pul[$pu] = intval($hsl[$i]);
$pu = $pu + 1;
}
if($hsl[$i] >=1000 && $hsl[$i] < 10000)
{
$th[$thou] = intval($hsl[$i]);
$thou = $thou + 1;
}
}
$th=array_unique($th);
$pul = array_unique($pul);
$ratus = array_unique($ratus);
sort($ratus);
sort($pul);
sort($th);
print_r($th);
function power_perms($arr) {
$power_set = power_set($arr);
$result = array();
foreach($power_set as $set) {
$perms = perms($set);
$result = array_merge($result,$perms);
}
return $result;
}
function power_set($in,$minLength = 1) {
$count = count($in);
$members = pow(2,$count);
$return = array();
for ($i = 0; $i < $members; $i++) {
$b = sprintf("%0".$count."b",$i);
$out = array();
for ($j = 0; $j < $count; $j++) {
if ($b{$j} == '1') $out[] = $in[$j];
}
if (count($out) >= $minLength) {
$return[] = $out;
}
}
// usort($return,"cmp"); //can sort here by length
return $return;
}
function factorial($int){
if($int < 2) {
return 1;
}
for($f = 2; $int-1 > 1; $f *= $int--);
return $f;
}
function perm($arr, $nth = null) {
if ($nth === null) {
return perms($arr);
}
$result = array();
$length = count($arr);
while ($length--) {
$f = factorial($length);
$p = floor($nth / $f);
$result[] = $arr[$p];
array_delete_by_key($arr, $p);
$nth -= $p * $f;
}
$result = array_merge($result,$arr);
return $result;
}
function perms($arr) {
$p = array();
for ($i=0; $i < factorial(count($arr)); $i++) {
$p[] = perm($arr, $i);
}
return $p;
}
function array_delete_by_key(&$array, $delete_key, $use_old_keys = FALSE) {
unset($array[$delete_key]);
if(!$use_old_keys) {
$array = array_values($array);
}
return TRUE;
}
?>

Solve Matrix with PHP

I want to solve a matrix with PHP. For example, if I have three points: (x0, y0), (x1, y1) and (x2, y2), I want to know what p[0], p[1] and p[2] is in y = p[2]*x^2 + p[1]*x^1 + p[0]*x^0, valid for all those points. If n points are given, I want to solve y = p[n] * x^n + p[n-1] * x^(n-1) + ... + p[0] * x^0. What I have at this point, is this:
<?php
$system = new EQ();
$system->add(1, 2);
$system->add(4, 5);
$system->solvePn(0);
class EQ {
private $points = array();
public function add($x, $y) {
$this->points[] = array($x, $y);
}
public function solvePn($n) {
// Solve p[n]
// So eliminate p[m], p[m-1], ..., p[n+1], p[n-1], ..., p[1], p[0]
$m = count($this->points);
$a = $m;
// Eliminate p[a]
if ($a != $n) {
}
$a--;
}
}
?>
But now I don't know what to do next.
Thanks davin and Roman. I used Lagrange for it, and it works fine now. For example, if there are 3 points given (1,1), (2,3), (3,27), the class will use Lagrange to calculate a polynomial approximation. Now you can call $system->f(4) to calculate the y-value for x=4 on this polynome.
<?php
$system = new EQ();
$system->add(1, 1);
$system->add(2, 3);
$system->add(3, 27);
echo $system->f(4);
class EQ {
private $points = array();
private $formula = NULL;
public function add($x, $y) {
$this->points[] = array($x, $y);
}
public function lz($z) {
$point = $this->points[$z];
// Get the x and y value of this point
$x = $point[0];
$y = $point[1];
// Now get all points except these and build the formula
$index = 0;
$above = '';
$below = 1;
foreach ($this->points as $point) {
if ($index != $z) {
$xp = $point[0];
$yp = $point[1];
$above .= '(x-' . $xp . ')';
$below *= ($x - $xp);
}
$index++;
}
$factor = $y / $below;
$above = ungroup($above);
foreach ($above as $degree=>$subfactor) {
$above[$degree] = $subfactor * $factor;
}
return $above;
}
public function f($x) {
if ($this->formula === NULL) $this->L();
$formula = $this->formula;
$val = 0;
foreach ($formula as $degree=>$factor) {
$subval = $factor * pow($x, $degree);
$val += $subval;
}
return $val;
}
public function L() {
$n = count($this->points);
$formula = array();
for ($z = 0; $z < $n; $z++) {
$l = $this->lz($z);
foreach ($l as $degree=>$factor) {
$formula[$degree] += $factor;
}
}
$this->formula = $formula;
return $formula;
}
}
// Transform a group-formula to a list with terms
// #example (x-1)*(x-2)
function ungroup($formula) {
preg_match_all('/\(([^)]{1,})\)/', $formula, $matches);
$groups = $matches[1];
$factorTerms = getTerms(reset($groups));
while (key($groups) < count($groups) - 1) {
next($groups);
$terms = getTerms(current($groups));
$newTerms = array();
foreach ($terms as $term) {
foreach ($factorTerms as $factorTerm) {
$degree = getDegree($term) + getDegree($factorTerm);
$factor = getFactor($term) * getFactor($factorTerm);
$newTerm = '';
if ($factor != 1) $newTerm = ($factor == -1?'-':$factor);
if ($degree != 0) $newTerm .= 'x' . ($degree == 1?'':'^' . $degree);
if (strlen($newTerm) == 0) $newTerm = '0';
$newTerms[] = $newTerm;
}
}
$factorTerms = $newTerms;
}
$terms = array();
foreach ($factorTerms as $term) {
$degree = getDegree($term);
$factor = getFactor($term);
$terms[$degree] += $factor;
}
return $terms;
}
function getFactor($term) {
if (strpos($term, 'x') !== false) {
$pattern = '/([0-9\-]{1,})[\*]?x/';
preg_match($pattern, $term, $matches);
if (count($matches) == 2) {
$n = $matches[1];
if ($n === '-') return -1;
return $n;
}
return 1;
}
return $term;
}
function getDegree($term) {
if (strpos($term, 'x') !== false) {
$pattern = '/x\^([0-9\-]{1,})/';
preg_match($pattern, $term, $matches);
if (count($matches) == 2) {
return $matches[1];
}
return 1;
}
return 0;
}
function getTerms($group) {
$group = str_replace('-', '+-', $group);
$group = preg_replace('/\+{1,}/', '+', $group);
$terms = explode('+', $group);
return $terms;
}
?>

Categories