How to take a single record from an array - php

I have a function that counts the number of points for each letter. I want her to count the points for each word. See this is my code:
function getValue() {
$letter = $this->getName(); // String from FORM
// Switch looks at a letter and assigns the value points for that letter
switch(true){
case($letter == 'a'||$letter == 'e'||$letter == 'i'||$letter == 'o'||$letter == 'u'||$letter == 'l'||$letter == 'n'||$letter == 's'||$letter == 't'||$letter == 'r'):
return 1;
case($letter == 'd'||$letter == 'g'):
return 2;
case($letter == 'b'||$letter == 'c'||$letter == 'm'||$letter == 'p'):
return 3;
case($letter == 'f'||$letter == 'h'||$letter == 'v'||$letter == 'w'||$letter == 'y'):
return 4;
case($letter == 'k'):
return 5;
case($letter == 'j'||$letter == 'x'):
return 8;
case($letter == 'q'||$letter == 'z'):
return 10;
default:
return 0;
}
}
function makeWordsPoint() {
$total_word_points = 0;
$words = $this->word_for_letters;
foreach ($words as $word) {
$total_word_points = $word->getValue();
}
echo $word . "=" . $total_word_points
}
How I can do it? Thanks for help
EDIT:
Okey, look now. There is my two classes Word and Letter
<?php
class Word
{
private $word;
private $words_with_points = array();
function __construct($user_letters)
{
$this->word = $user_letters;
// creates array of object word for letters
$this->word_for_letters = $this->makeWordForLetters();
// creates array of letter objects for the word
$this->words_with_points = $this->makeWordsWithPoints();
}
function makeWordForLetters()
{
$word_objects = array();
$word = $this->getWord();
$file = file_get_contents( __DIR__."/../src/dictionary.txt");
$items = explode("\n", $file);
$letters = str_split($word);
foreach ($items as $item) {
$list = $letters;
// remove the original word (once)
$thisItem = preg_replace("/$word/", '', $item, 1);
for ($i = 0; $i < strlen($thisItem); $i++) {
$index = array_search($thisItem[$i], $list);
if ($index === false) {
continue 2; // letter not available
}
unset($list[$index]); // remove the letter from the list
}
array_push($word_objects, $item);
}
return $word_objects; // passed!
}
function makeWordsWithPoints()
{
$word = $this->makeWordForLetters();
$letter_objects = array();
foreach ($word as $character) {
array_push($letter_objects, new Letter($character));
}
return $letter_objects;
}
function getWord()
{
return $this->word;
}
function getWordForLetters()
{
return $this->word_for_letters;
}
function getWordsWithPoints()
{
return $this->words_with_points;
}
}
?>
<?php
class Letter
{
private $name;
private $value;
function __construct($letter)
{
$letter = strtolower($letter);
$this->name = $letter;
$this->value = $this->setValue();
}
function getName()
{
return $this->name;
}
function getValue()
{
return $this->value;
}
function setValue()
{
$letter = $this->getName();
switch(true){
case($letter == 'a'||$letter == 'e'||$letter == 'i'||$letter == 'o'||$letter == 'u'||$letter == 'l'||$letter == 'n'||$letter == 's'||$letter == 't'||$letter == 'r'):
return 1;
case($letter == 'd'||$letter == 'g'):
return 2;
case($letter == 'b'||$letter == 'c'||$letter == 'm'||$letter == 'p'):
return 3;
case($letter == 'f'||$letter == 'h'||$letter == 'v'||$letter == 'w'||$letter == 'y'):
return 4;
case($letter == 'k'):
return 5;
case($letter == 'j'||$letter == 'x'):
return 8;
case($letter == 'q'||$letter == 'z'):
return 10;
default:
return 0;
}
}
}
?>
And now when I write in now letters like this: loso function makeWordForLetters() search in my array correctly words for this letters and I display this words with points by makeWordsWithPoint like this:
l - 1
lo - 0
loo - 0
loos - 0
los - 0
oslo - 0
s - 1
solo - 0
But as you can see the score is incorrect because it displays the result for a single letter and not for a word.
How can I solve this problem?

take it as string, then use preg_split function, count new array length.eg:
$string="php教程#php入门:教程#字符串:多分隔符#字符串:拆分#数组";
$arr = preg_split("/(#|:)/",$string);
print_r($arr);

Try this code instead. I think it's cleaner.
<?php
// set the score of each char into array
const SCORES = [
// 1
'a'=> 1,
'e' => 1,
'i' => 1,
'o' => 1,
'u' => 1,
'l' => 1,
'n' => 1,
's' => 1,
't' => 1,
'r' => 1,
// 2
'd'=> 2,
'g'=> 2,
// 3
'b'=> 3,
'c'=> 3,
'm'=> 3,
'p'=> 3,
// 4
'f'=> 4,
'h'=> 4,
'v'=> 4,
'w'=> 4,
'y'=> 4,
// 5
'k'=> 5,
// 8
'j'=> 8,
'x'=> 8,
// 10
'q'=> 10,
'z'=> 10,
];
$word = 'abcdef'; // get the string from the request here
# print_r($word);
$chars = str_split($word); // split string into array of chars
# print_r($chars);
$scores = array_map(function($char) { // create a scores array that convert char into value
return SCORES[strtolower($char)] ?? 0; // get the score of each char and set to the array, if not exist set to 0
}, $chars);
# print_r($scores);
$totalScore = array_sum($scores); // get the sum of the scores
echo $word . "=" . $totalScore;
Let me know if you have any question.

Related

php calculate string values: "2+4+3-12+3-5"

How can I calculate values in a string containing the following numbers and (+/-) operators:
Code Like
$string = "3+5+3-7+4-3-1";
//result should be = 4
Updated:
I am trying to calculate $array = [1, +, 6, -, 43, +, 10];
I have converted into the string: implode("", $array);
you can use eval
$string = "3+5+3-7+4-3-1";
eval( '$res = (' . $string . ');' );
echo $res;
$arr_val = array(1, '+', 6, '-', 43, '+', 10);
$total = 0;
if(isset($arr_val[0]) && ($arr_val[0] != '+' || $arr_val[0] != '-'))
$total = intval($arr_val[0]);
foreach($arr_val AS $key => $val) {
if($val == '+') {
if(isset($arr_val[$key+1]) && ($arr_val[$key+1] != '+' || $arr_val[$key+1] != '-')) {
$total = $total + intval($arr_val[$key+1]);
}
} else if($val == '-') {
if(isset($arr_val[$key+1]) && ($arr_val[$key+1] != '+' || $arr_val[$key+1] != '-')) {
$total = $total - intval($arr_val[$key+1]);
}
}
}
echo $total;
May be it will solve your problem.
For any kind of array like: [1, + , 4, -, 5, , 3, 8, + , 6]
Solved with the custom php helper function:
function calcArray($arrVal)
{
if (count($arrVal) == 1) {
return reset($arrVal);
}
if (is_int($arrVal[1])) {
$arrVal[0] = $arrVal[0].$arrVal[1];
unset($arrVal[1]);
return calcArray(array_values($arrVal));
}
$emptyValKey = array_search('', $arrVal);
if ($emptyValKey) {
$concatVal = $arrVal[$emptyValKey-1].$arrVal[$emptyValKey+1];
unset($arrVal[$emptyValKey+1]);
unset($arrVal[$emptyValKey]);
$arrVal[$emptyValKey-1] = $concatVal;
return calcArray(array_values($arrVal));
}
$total = $arrVal[1] == "+" ? $arrVal[0] + $arrVal[2]:$arrVal[0] - $arrVal[2];
unset($arrVal[0]);
unset($arrVal[1]);
unset($arrVal[2]);
array_unshift($arrVal, $total);
$arrVal = array_values(array_filter($arrVal));
return calcArray($arrVal);
}

How to find backward primes within a range of integers?

I'm trying to solve a backward prime question.
Following is the question:
Find all Backwards Read Primes between two positive given numbers (both inclusive), the second one being greater than the first one. The resulting array or the resulting string will be ordered following the natural order of the prime numbers.
Example
backwardsPrime(2, 100) => [13, 17, 31, 37, 71, 73, 79, 97]
backwardsPrime(9900, 10000) => [9923, 9931, 9941, 9967]
I tried doing something like this:
public function backwardPrime()
{
$start = 7000;
$stop = 7100;
$ans = [];
while($start <= $stop)
{
if($start > 10)
{
if($start !== $this->reverse($start))
{
if($this->isPrime($start) && $this->isPrime($this->reverse($start)))
{
array_push($ans, $start);
}
}
}
$start++;
}
return $ans;
}
public function reverse($num)
{
$reverse = 0;
while($num > 0)
{
$reverse = $reverse * 10;
$reverse = $reverse + $num%10;
$num = (int)($num/10);
}
return $reverse;
}
public function isPrime($num)
{
if($num == 1 || $num == 2 || $num == 3)
return true;
elseif ($num%2 == 0 || $num%3 == 0)
return false;
else
{
$i=5;
while($i<=$num/2)
{
if($num%$i===0)
{
return false;
}
$i++;
}
}
return true;
}
I'm able to get the appropriate answer but while doing the same in single function I'm not able to get it:
public function backwardPrimes()
{
$start = 7000;
$stop = 7100;
$ans = [];
while($start <= $stop)
{
$isStartPrime = true;
$isReversePrime = true;
if($start > 10)
{
$reverse = 0;
$num = $start;
while($num > 0)
{
$reverse = $reverse * 10;
$reverse = $reverse + $num%10;
$num = (int)($num/10);
}
if($start !== $reverse)
{
if($start%2 != 0 && $start%3 != 0)
{
$i =5;
while($i<=$start/2)
{
if($start%$i === 0)
{
$isStartPrime = false;
break;
}
$i++;
}
}
if($reverse%2 != 0 && $reverse%3 != 0)
{
$i =5;
while($i<=$reverse/2)
{
if($reverse%$i === 0)
{
$isReversePrime = false;
break;
}
$i++;
}
}
if($isStartPrime && $isReversePrime)
{
array_push($ans, $start);
}
}
}
$start++;
}
return $ans;
}
I don't know where I'm having mistake, guide me.
Thanks.
An emirp ("prime" spelled backwards) is a prime whose (base 10) reversal is also prime, but which is not a palindromic prime. in other words
Backwards Read Primes are primes that when read backwards in base 10 (from right to left) are a different prime. (This rules out primes which are palindromes.)
try this short solution in which I use two helper function reverse and isPrime :
isPrime: Thanks to #Jeff Clayton for his method to test prime numbers, for more information click the link below https://stackoverflow.com/a/24769490/4369087
reverse: that use the php function [strrev()][1], this method take a string a reverse it, we'll use this trick to reverse a number by converting it to a string reverse it and converting back to an integer.
backwardsPrime: this last function's job is itterating over a range of numbers from $min value to $max value and test if the number if a prime number and it's reverse is a prime number as well and it's not a palindrome number if all of those conditions are true then we addit to the result array.
implementation
function isPrime($number)
{
return !preg_match('/^1?$|^(11+?)\1+$/x', str_repeat('1', $number));
}
function reverse($n)
{
return (int) strrev((string) $n);
}
function backwardsPrime($min, $max)
{
$result = [];
foreach(range($min, $max) as $number) {
$reverse = reverse($number);
if($reverse !== $number && isPrime($number) && isPrime($reverse)) {
$result[] = $number;
}
}
return $result;
}
echo "<pre>";
print_r(backwardsPrime(2, 100));
print_r(backwardsPrime(9900, 10000));
output :
Array
(
[0] => 13
[1] => 17
[2] => 31
[3] => 37
[4] => 71
[5] => 73
[6] => 79
[7] => 97
)
Array
(
[0] => 9923
[1] => 9931
[2] => 9941
[3] => 9967
)
you can even optimize the backwardsPrime function like this :
function backwardsPrime($min, $max)
{
$result = [];
foreach(range($min, $max) as $number) {
$reverse = reverse($number);
if($reverse !== $number && !in_array($number, $result) && isPrime($number) && isPrime($reverse)) {
$result[] = $number;
}
}
return $result;
}

PHP evaluating the content of an array

I am trying to evaluate the content of an array. The array contain water temperatures submitted by a user.
The user submits 2 temperaures, one for hot water and one for cold water.
What I need is to evaluate both array items to find if they are within the limits, the limits are "Hot water: between 50 and 66", "Cold water less than 21".
If either Hot or Cold fail the check flag the Status "1" or if they both pass the check flag Status "0".
Below is the code I am working with:
$row_WaterTemp['HotMin'] = "50";
$row_WaterTemp['Hotmax'] = "66";
$SeqWaterArray new(array);
$SeqWaterArray = array("58", "21");
foreach($SeqWaterArray as $key => $val) {
$fields[] = "$field = '$val'";
if($key == 0) {
if($val < $row_WaterTemp['HotMin'] || $val > $row_WaterTemp['Hotmax']) {
$Status = 1;
$WaterHot = $val;
} else {
$Status = 0;
$WaterHot = $val;
}
}
if($key == 1) {
if($val > $row_WaterTemp['ColdMax']) {
$Status = 1;
$WaterCold = $val;
} else {
$Status = 0;
$WaterCold = $val;
}
}
}
My question is:
When I run the script the array key(0) works but when the array key(1) is evaluted the status flag for key(1) overrides the status flag for key0.
If anyone can help that would be great.
Many thanks for your time.
It seems OK to me, exept for the values at limit, and you can simplify
$row_WaterTemp['HotMin'] = "50";
$row_WaterTemp['Hotmax'] = "66";
$SeqWaterArray = array("58", "21");
$Status = array() ;
foreach($SeqWaterArray as $key => $val) {
if($key == 0) {
$Status = ($val >= $row_WaterTemp['HotMin'] && $val <= $row_WaterTemp['Hotmax']) ;
$WaterHot = $val;
} else if($key == 1) {
$Status += ($val >= $row_WaterTemp['ColdMax']) ;
$WaterCold = $val;
}
}
If one fails, $Status = 1, if the two tests failed, $Status = 2, if it's ok, $Status = 0.
<?php
// this function return BOOL (true/false) when the condition is met
function isBetween($val, $min, $max) {
return ($val >= $min && $val <= $max);
}
$coldMax = 20; $hotMin = 50; $hotMax = 66;
// I decided to simulate a test of more cases:
$SeqWaterArray['john'] = array(58, 30);
$SeqWaterArray['martin'] = array(34, 15);
$SeqWaterArray['barbara'] = array(52, 10);
foreach($SeqWaterArray as $key => $range) {
$flag = array();
foreach($range as $type => $temperature) {
// here we fill number 1 if the temperature is in range
if ($type == 0) {
$flag['hot'] = (isBetween($temperature, $hotMin, $hotMax) ? 0 : 1);
} else {
$flag['cold'] = (isBetween($temperature, 0, $coldMax) ? 0 : 1);
}
}
$results[$key]['flag'] = $flag;
}
var_dump($results);
?>
This is the result:
["john"]=>
"flag"=>
["hot"]=> 1
["cold"]=> 0
["martin"]=>
"flag" =>
["hot"]=> 1
["cold"]=> 0
["barbara"]=>
"flag" =>
["hot"]=> 0
["cold"]=> 0
I don't think that you need a foreach loop here since you are working with a simple array and apparently you know that the first element is the hot water temperature and the second element is the cold water temperature. I would just do something like this:
$row_WaterTemp['HotMin'] = 50;
$row_WaterTemp['HotMax'] = 66;
$row_WaterTemp['ColdMax'] = 21;
$SeqWaterArray = array(58, 21);
$waterHot = $SeqWaterArray[0];
$waterCold = $SeqWaterArray[1];
$status = 0;
if ($waterHot < $row_WaterTemp['HotMin'] || $waterHot > $row_WaterTemp['HotMax']) {
$status = 1;
}
if ($waterCold > $row_WaterTemp['ColdMax']) {
$status = 1;
}
You can combine the if statements of course. I separated them because of readability.
Note that I removed all quotes from the numbers. Quotes are for strings, not for numbers.
You can use break statement in this case when the flag is set to 1. As per your specification the Cold water should be less than 21, I have modified the code.
<?php
$row_WaterTemp['HotMin'] = "50";
$row_WaterTemp['Hotmax'] = "66";
$row_WaterTemp['ColdMax'] = "21";
$SeqWaterArray = array("58", "21");
foreach($SeqWaterArray as $key => $val) {
$fields[] = "$key = '$val'";
if($key == 0) {
if($val < $row_WaterTemp['HotMin'] || $val > $row_WaterTemp['Hotmax']) {
$Status = 1;
$WaterHot = $val;
break;
} else {
$Status = 0;
$WaterHot = $val;
}
}
if($key == 1) {
if($val >= $row_WaterTemp['ColdMax']) {
$Status = 1;
$WaterCold = $val;
break;
} else {
$Status = 0;
$WaterCold = $val;
}
}
}
echo $Status;
?>
This way it would be easier to break the loop in case if the temperature fails to fall within the range in either case.
https://eval.in/636912

Printing pattern sequence of 3 characters

I would like to print pattern of 3 characters using PHP. Like aaa, aab, aac .... zzz.
Now, I am using these PHP code but it is printing randomly instead sequence.
$i = 1;
$chars = array("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z");
while($i > 0){ $current = $chars[rand(0,25)].$chars[rand(0,25)].$chars[rand(0,25)]; }
Quick but sloppy
$i=0;
$j=0;
$k=0;
while($i<26){
while($j<26){
while($k<26){
echo $chars[$i] . $chars[$j] . $chars[$k];
$k++;
}
$j++;
$k=0;
}
$i++;
$j=0;
$k=0;
}
Count from 0 to 26^3 -1. Then convert your numbers to base 26 , replace numbers by letters as needed, and prefix with "a" or "aa" if the converted result is single or double digit.
Use this function: string base_convert ( string $number , int $frombase , int $tobase )
I am not going to code it all out for you. You need to learn from it.
I got it in c#.
string sample = "AAA";
char[] chars = sample.ToCharArray();
char first = chars[0];
char second = chars[1];
char third = chars[2];
if (first == second && first == third)
{
third++;
bool isAlphaBet = Regex.IsMatch(third.ToString(), "[a-z]", RegexOptions.IgnoreCase);
if (isAlphaBet)
{
return $"{first}{second}{third}";
}
return $"empty";
}
if (first == second && first != third)
{
third++;
bool isAlphaBet = Regex.IsMatch(third.ToString(), "[a-z]", RegexOptions.IgnoreCase);
if (isAlphaBet)
{
return $"{first}{second}{third}";
}
else
{
second++;
third = 'A';
return $"{first}{second}{third}";
}
}//"ABA";
if (first != second && first == third)
{
third++;
bool isAlphaBet = Regex.IsMatch(third.ToString(), "[a-z]", RegexOptions.IgnoreCase);
if (isAlphaBet)
{
return $"{first}{second}{third}";
}
else
{
second++;
third = 'A';
return $"{first}{second}{third}";
}
}
if (first != second && first != third && second != third)
{
third++;
bool isAlphaBet = Regex.IsMatch(third.ToString(), "[a-z]", RegexOptions.IgnoreCase);
if (isAlphaBet)
{
return $"{first}{second}{third}";
}
else
{
second++;
third = 'A';
bool isAlphaBetSecond = Regex.IsMatch(second.ToString(), "[a-z]", RegexOptions.IgnoreCase);
if (isAlphaBetSecond)
{
return $"{first}{second}{third}";
}
else
{
second = 'A';
first++;
bool isAlphaBetFirst = Regex.IsMatch(first.ToString(), "[a-z]", RegexOptions.IgnoreCase);
if (isAlphaBetFirst)
{
return $"{first}{second}{third}";
}
else
{
return $"empty";
}
}
}
}
if (first != second && second == third)
{
third++;
bool isAlphaBetThird = Regex.IsMatch(third.ToString(), "[a-z]", RegexOptions.IgnoreCase);
if (isAlphaBetThird)
{
return $"{first}{second}{third}";
}
else
{
third = 'A';
second++;
bool isAlphaBetSecond = Regex.IsMatch(second.ToString(), "[a-z]", RegexOptions.IgnoreCase);
if (isAlphaBetSecond)
{
return $"{first}{second}{third}";
}
else
{
second = 'A';
first++;
bool isAlphaBetFirst = Regex.IsMatch(first.ToString(), "[a-z]", RegexOptions.IgnoreCase);
if (isAlphaBetFirst)
{
return $"{first}{second}{third}";
}
else
{
return $"empty";
}
}
}
}
return $"{first}{second}{third}";
If you need to print random - like 'aaa' or 'vvv' or 'ddd' - try to use
$char = $chars[rand(0,25)];
echo $current = $char.$char.$char;
If you want to print 'aaa','bbb','ccc',...- use
for ($i = 0; $i < 26; $i++) {
$char = $chars[$i];
echo $current = $char.$char.$char;
}

PHP: Sort array according to another array of different length

I have two arrays of different length:
$paths_table = array("TS-0007_a.jpg", "TS-0040_a.JPG", "TS-0040_b.JPG", "TS-0040_f.JPG", "TS-0041_a.JPG", "TS-0041_b.JPG");
$order_table = array("TS-0040","TS-0007","TS-0041");
and I want to sort the first one using the second so that the output will be the array
$final_table = array("TS-0040_a.JPG", "TS-0040_b.JPG", "TS-0040_f.JPG", "TS-0007_a.jpg", TS-0041_a.JPG", "TS-0041_b.JPG")
Assuming that I'm going to use
strpos($paths_table[$i], $order_table[$j]);
to check if the string of $order_table is included in any of the $paths_table.
How can I accomplish this?
Preprocess the array so that each item contains an index of its prefix (that is, turn 'TS-0007_a.jpg' into [1,'TS-0007_a.jpg']):
foreach($paths_table as &$v) {
foreach($order_table as $n => $o)
if(strpos($v, $o) === 0) {
$v = [$n, $v];
break;
}
}
sort the array:
sort($paths_table);
and remove indexes:
foreach($paths_table as &$v)
$v = $v[1];
The following piece of code can off course be optimized in several ways, but for the sake of clarity I didnt.
$paths_table = array("TS-0007_a.jpg", "TS-0040_a.JPG", "TS-0040_b.JPG", "TS-0040_f.JPG", "TS-0041_a.JPG", "TS-0041_b.JPG");
$order_table = array("TS-0040","TS-0007","TS-0041");
$sorter = new PrefixSorter($order_table);
$output = usort($paths_table, array($sorter, 'sort'));
var_dump($paths_table);
class PrefixSorter {
private $prefixes;
function __construct($prefixes) {
$this->prefixes = $prefixes;
}
function sort($path1, $path2) {
$prefix1 = -1;
$prefix2 = -1;
foreach($this->prefixes as $index=>$prefix) {
if (substr($path1, 0, strlen($prefix)) == $prefix) $prefix1 = $index;
if (substr($path2, 0, strlen($prefix)) == $prefix) $prefix2 = $index;
}
if (($prefix1 == -1 && $prefix2 == -1) || $prefix1 == $prefix2) {
return 0;
}
else if ($prefix1 == -1 || $prefix1 > $prefix2) {
return 1;
}
else if ($prefix2 == -1 || $prefix1 < $prefix2) {
return -1;
}
}
}
I made a few assumptions:
You want to sort on the prefixes given in order_table
Prefixes not given are put at the back unordered.
You can off course change the code to match on string containment instead of prefixing

Categories