php - permutation - possible number - php

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;
}
?>

Related

Unneccesary new line php

I have a PHP code. The code is supposed to print the output followed by a new line.
The code works fine but i have unneccesary new line at the end. There should be only one newline at the end, but my code prints several new lines. What could be the issue? Please help.
<?php
/* Read input from STDIN. Print your output to STDOUT*/
$fp = fopen("php://stdin", "r");
//Write code here
$loop = 0;
$n = 0; $arr = [];
while(!feof($fp)) {
$arr = []; $n = 0;
if($loop == 0) {
$total = fgets($fp);
}
else {
if($loop%2 == 1) {
$n = fgets($fp);
}
else {
$arr = fgets($fp);
}
}
if($loop > 0 && $loop%2 == 0) {
$arr = explode(" ", $arr);
$m = [];
for($i = 0; $i < 1<<10; $i++) {
$m[$i] = -1;
}
$n = count($arr);
$r = 0;
for($i = 0; $i < 1<<10; $i++) {
$r = max($r, fd_sum($i, $m, $arr, $n));
}
echo $r."\n";
}
$loop++;
}
fclose($fp);
?>
<?php
function fd_sum($i, $m, $arr, $n) {
if($i == 0) {
return $m[$i] = 0;
}
else if($m[$i] != -1) {
return $m[$i];
}
else {
$rr = 0;
for($j = 0; $j < $n; $j++) {
$num = (int)$arr[$j];
$b = save($num);
if(($i | $b) == $i) {
$z = $i^save($num);
$y = fd_sum($z, $m, $arr, $n);
$v = ($y + $num);
$rr = max($v, $rr);
}
}
return $m[$i] = $rr;
}
}
?>
<?php
function save($nm)
{
$x = 0;
for($i = 1; $nm/$i > 0; $i *= 10) {
$d = ($nm/$i) % 10;
$x = $x | (1 << $d);
}
return $x-1;
}
?>
My input is
3
4
3 5 7 2
5
121 3 333 23 4
7
32 42 52 62 72 82 92
My output is
17
458
92
-
-
-
-
The expected output is
17
458
92
-
Note : I have used '-' to indicate a new line
What am i doing wrong? Please help.
The PHP interpreter is reading the new lines after the closing tags and just spitting it right back out as output. Removing the extra opening/closing tags should remove the extra new lines.
Also, php closing tags are not necessary and i recommend omitting them.
<?php
/* Read input from STDIN. Print your output to STDOUT*/
$fp = fopen("php://stdin", "r");
//Write code here
$loop = 0;
$n = 0; $arr = [];
while(!feof($fp)) {
$arr = []; $n = 0;
if($loop == 0) {
$total = fgets($fp);
}
else {
if($loop%2 == 1) {
$n = fgets($fp);
}
else {
$arr = fgets($fp);
}
}
if($loop > 0 && $loop%2 == 0) {
$arr = explode(" ", $arr);
$m = [];
for($i = 0; $i < 1<<10; $i++) {
$m[$i] = -1;
}
$n = count($arr);
$r = 0;
for($i = 0; $i < 1<<10; $i++) {
$r = max($r, fd_sum($i, $m, $arr, $n));
}
echo $r."\n";
}
$loop++;
}
fclose($fp);
function fd_sum($i, $m, $arr, $n) {
if($i == 0) {
return $m[$i] = 0;
}
else if($m[$i] != -1) {
return $m[$i];
}
else {
$rr = 0;
for($j = 0; $j < $n; $j++) {
$num = (int)$arr[$j];
$b = save($num);
if(($i | $b) == $i) {
$z = $i^save($num);
$y = fd_sum($z, $m, $arr, $n);
$v = ($y + $num);
$rr = max($v, $rr);
}
}
return $m[$i] = $rr;
}
}
function save($nm)
{
$x = 0;
for($i = 1; $nm/$i > 0; $i *= 10) {
$d = ($nm/$i) % 10;
$x = $x | (1 << $d);
}
return $x-1;
}

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.

Making array after explode

I want to create an array from an input string. Before this code, I've tried explode, but the array remains length 1. Each string that I've tried is still one in array[0]. Here's my code so far:
public function word()
{
$kata = array($this->kal->getHasil());
if (!empty($kata)) {
$n = count($kata)
for ($i = 0; $i < $n; $i++) {
$imin = $i;
for ($j = $i; $j < $n; $j++) {
if ($kata[$j] < $kata[$imin]) {
$imin = $j;
}
}
$temp = $kata[$i];
$kata[$i] = $kata[$imin];
$kata[$imin] = $temp;
}
for ($i = 0; $i < $n; $i++) {
echo "$kata[$i] ";
}
}
}
public function tokenize()
{
$temp = $this->kal->getHasil();
$token = explode(" ", $temp);
return $token;
}
$hasil = $pp->tokenize();
for ($i = 0; $i < sizeof($hasil); $i++) {
$st = new stemming();
$hasil[$i] = $pp->singkatan($hasil[$i]);
$hasil[$i] = $st->stem($hasil[$i]);
$hasil[$i] = $pp->stopWord($hasil[$i]);
//echo "$hasil[$i] ";
$hb = new hitungBobot($hasil[$i]);
$hb->word();
}
How would I fix this?
You can use a globar var, see the code:
public function word(){ $kata = array($this->kal->getHasil());
global $output;
if(!empty($kata)){
$ar= count($kata)
$output += $ar;
}
public function tokenize() {
$temp = $this->kal->getHasil();
$token = explode(" ",$temp);
return $token;
}
$output = 0;
$hasil = $pp->tokenize();
for($i=0; $i<sizeof($hasil); $i++) {
$st = new stemming();
$hasil[$i] = $pp->singkatan($hasil[$i]);
$hasil[$i] = $st->stem($hasil[$i]);
$hasil[$i] = $pp->stopWord($hasil[$i]);
//echo "$hasil[$i] ";
$hb = new hitungBobot($hasil[$i]);
$hb->word();
}
echo $output;

Seven flags to concise list of days of the week?

I have an array/string/integer of 7 flags, one for each day of the week (of a recurring event). How can I convert this to a brief list of the days?
So, for example
Given 1011001, return 'Su, T-W, Sa'.
Given 0111011, return 'M-W, F-Sa'.
What's the shortest way to accomplish this?
EDIT
For comparison, here's my own inelegant code:
<?php
function dowstring($dow) {
if ($dow == 0) return "Error";
$ddow = ["Su", "M", "T", "W", "Th", "F", "Sa"];
$t = strrev( sprintf('%07b', $dow) );
$u = str_split($t);
$out = '';
$cu = count($u);
$nn = 0; // number of days thus far counted
$v = 0; // number in the run
for($i = 0; $i < $cu; $i++) {
if ($u[$i]) {
if ($v == 0) {
$out .= ($nn) ? ", " : '';
$out .= $ddow[$i];
}
$nn++;
$v++;
}
else {
if ($v > 1) {
$out .= ($nn) ? "-" . $ddow[$i-1] : '';
}
$v = 0;
}
}
// in case Saturday is part of a run
if ($v > 1) {
$out .= ($nn) ? "-" . $ddow[$i-1] : '';
}
return $out;
}
echo "<pre>";
// testing script
for ($i = 1; $i < pow(2, 7); $i++) {
$ds = dowstring($i);
$j = strrev( sprintf("%07b", $i) );
printf("%s %s\n", $j, $ds);
}
echo "</pre>";
?>
EDIT
Another attempt, inspired by Prasanth:
function dowstring($dow) {
if ($dow == 0) return "Error";
$ddow = ["Su", "M", "T", "W", "Th", "F", "Sa"];
$t = strrev( sprintf('%07b', $dow) );
$v = array_keys( array_filter( str_split($t) ) );
$cv = count($v); $w = array();
$out = $ddow[$v[0]];
for ($i = 1; $i < $cv; $i++) $w[] = $v[$i] - $v[$i - 1] - 1;
$w = ( $cv == 1 ) ? array($w) : $w;
for ($i = 1; $i < $cv; $i++) {
if (!$w[$i - 1]) $last = $ddow[$v[$i]];
else {
if ( isset($last) ) $out .= '-' . $last;
$out .= ', ' . $ddow[$v[$i]];
unset($last);
}
}
if ($i > 1 && !$w[$i-2] ) $out .= '-' . $ddow[ $v[$i-1] ];
return $out;
}
I'd like to see something better. Anyone?
Try this:
$days=array('1'=>'Monday','2'=>'Tuesay','3'=>'Wednesday','4'=>'Thursday','5'=>'Friday','6'=>'Saturday','7'=>'Sunday');
$pattern = '1000110';
$arr1 = str_split($pattern);
$i=0;
foreach($days as $key => $tes) {
if($key - $arr1[$i] != $key) {
echo $tes;
}
$i++;
}
Adjust days array according to the sequence of days you want
Try this :
<?php
$days = array('Su','M','T','W','Th','F','Sa');
function checkConsec($d) {
for($i=0;$i<count($d);$i++) {
if(isset($d[$i+1]) && $d[$i]+1 != $d[$i+1]) {
return false;
}
}
return true;
}
$str = '0111011';
$array = array_keys(array_filter(str_split($str)));
$temp = array();
$res = array();
for($i=0;$i<count($array);$i++){
$temp[] = $array[$i];
if(checkConsec($temp) && count($temp) > 1){
$res[$temp[0]] = $days[$temp[0]]."-".$days[$temp[count($temp)-1]];
}else{
$res[$array[$i]] = $days[$array[$i]];
$temp = array();
$temp[] = $array[$i];
}
}
echo implode(",",$res);
?>

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