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;
}
?>
Related
I am trying to implement a function below:
For example:
$a=array(1,10,25,50);
$number=15;
o/p : 15=1+1+1+1+1+10;
Done:
$a=array(1,10,25,50);
rsort($a);
$number=15;
$final = [];
$remainder = $number;
foreach($a as $num) {
do {
if($num <= $number) {
$final[] = $num;
$remainder -= $num;
}
if($remainder == 0) break;
} while($remainder >= $num);
}
echo $number . " = " . implode(' + ', $final);
Also this method:
$a=array(1,10,25,50);
rsort($a);
$number=15;
echo $number . " = ";
$final = [];
foreach($a as $num) {
if((int)($number / $num) > 0) {
$final = array_merge($final, array_fill(0, (int)($number / $num), $num));
$number -= (int)($number / $num) * $num;
}
}
echo implode(' + ', $final);
Make a recursive function for this:
function getcomb($arr,$actualNum, $total=0, $combination_array = array()){
foreach($arr as $k=>$v){
if($v > $actualNum) continue;
$shiftVal = $v;
if($total+$shiftVal <= $actualNum ){
$combination_array[] = $shiftVal;
$total += $shiftVal;
$reminder = $actualNum-$total;
//echo "<pre>combination_array";print_r($combination_array);
if($reminder <= 0){
return $shiftVal;
}else{
return $shiftVal .' + '.getcomb($arr, $actualNum,$total, $combination_array);
}
}
}
}
$a=array(1,10,25,50);
rsort($a);
$number=15;
echo $str = getcomb($a, $number);
Cleck here to check output
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!!
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;
}
?>
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);
I have a problem with an advanced loop, this are my arrays
$array1 = array(1,2,3);
$array2 = array(4,5);
$array3 = array(6,7,8,9);
$array4 = array(10,11);
I want to loop with the following result:
1,4,6,10
1,4,6,11
1,4,7,10
1,5,7,11
With the last: 3,5,8,11
How can I do that?
Solution for a variable number of arrays. Can probably be written a bit shorter, but I leave that to you. ;)
<?php
$array1 = array(1,2,3);
$array2 = array(4,5);
$array3 = array(6,7,8,9);
$array4 = array(10,11);
function turboArray()
{
$arrays = func_get_args();
$indexes = array_fill(0, count($arrays), 0);
function turboSubArray(&$arrays, &$indexes, $l){
for ($a = 0; $a < count($arrays[$l]); $a++){
$indexes[$l] = $a;
if ($l == count($arrays) - 1) {
for ($i = 0; $i < count($indexes); $i++)
{
echo $arrays[$i][$indexes[$i]];
if ($i == count($indexes) - 1){
echo "\n<br/>";
$indexes[$i] = 0;
if ($i == 0) return;
}
else {
echo ', ';
}
}
} else if ($l < count($indexes)) {
turboSubArray($arrays, $indexes, $l + 1);
}
}
}
$l = 0;
turboSubArray($arrays, $indexes, $l);
}
turboArray($array1, $array2, $array3, $array4);
This should do it... ?
foreach ($array1 as $first) {
foreach ($array2 as $second) {
foreach ($array3 as $third) {
foreach ($array4 as $fourth) {
echo "$first $second $third $fourth";
}
}
}
}
I got bored and decided to overengineer a bit. Enjoy.
class CrossJoin implements Iterator {
private $arrays = array();
private $index = 0;
public function __construct(/* $array1, ... */) {
foreach (func_get_args() as $arr) {
// ArrayIterator's iteration stuff is cleaner than arrays',
// and less prone to breakage when objects are passed around
if (count($arr)) $this->arrays[] = new ArrayIterator($arr);
}
// if any of the arrays were empty, a cross join should fail.
// fudge a single empty array to prevent special-casing later
if (count($this->arrays) !== func_num_args()) {
$this->arrays = array(new ArrayIterator(array()));
}
}
public function next() {
for ($i = count($this->arrays) - 1; $i >= 0; --$i) {
// carry til we don't have to anymore
$place = $this->arrays[$i];
$place->next();
if ($place->valid()) break;
}
// if $i<0, then we carried right off the edge of the list.
// don't let $arrays[0] be reset, cause that's our indicator
// that we're done.
if ($i<0) return;
++$this->index;
for (++$i; $i < count($this->arrays); ++$i) {
$this->arrays[$i]->rewind();
}
}
public function current() {
$result = array();
foreach ($this->arrays as $arr) { $result[] = $arr->current(); }
return $result;
}
public function key() { return $this->index; }
public function valid() {
return !empty($this->arrays) && $this->arrays[0]->valid();
}
public function rewind() {
foreach ($this->arrays as $arr) $arr->rewind();
$this->index = 0;
}
}
$combos = new CrossJoin(
array(1, 2, 3),
array(4, 5),
array(6, 7, 8, 9),
array(10, 11)
);
foreach ($combos as $combo) {
echo implode(', ', $combo), "\n";
}
Hope that helps:
for ($i = 0; $i < count($a1); ++i) {
for ($j = 0; $j < count($a2); ++j) {
for ($k = 0; $k < count($a3); ++k) {
for ($l = 0; $l < count($a4); ++l) {
echo $a1[$i] . ' ' . $a2[$j] . ' ' . $a3[$k] . ' ' . $a4[$l] . '\n';
}
}
}
}
Cheers!
You are looking for the PHP array_merge function.