I have to find a php code to solve a math problem.
This is the problem description:
Players A and B are playing a new game of stones. There are N stones
placed on the ground, forming a sequence. The stones are labeled from
1 to N. Players A and B play in turns take exactly two consecutive stones
on the ground until there are no consecutive stones on the ground.
That is, each player can take stone i and stone i+1, where 1≤i≤N−1. If
the number of stone left is odd, A wins. Otherwise, B wins. Assume
both A and B play optimally and A plays first, do you know who the
winner is?
The line has N stones and are indexed from 1 to N --> N (1 ≤
N ≤ 10 000 000)
If the number of stone left is odd, A wins. Otherwise, B wins.
This is my code. It does work, but it is not correct.
<?php
$nStones = rand(1, 10000000);
$string = ("i");
$start = rand(1, 10000000);
$length = 2;
while($nStones > 0) {
substr( $nStones , $start [, $length ]): string;
}
if ($nStones % 2 == 1) {
echo "A";
} else {
echo "B";
}
?>
I think am missing the alternant subtraction of two consecutive stones by A & B, while $nStones > 0. Furthermore, the problem description mentions an optima subtraction until there is only one stone left. Therefore I guess the stones move together to their closest stones (the gaps disappear and are replaced by the closest stones).
I've made a start here:
<?php
class GameOfStones
{
const STONE_PAIR = 'OO';
const GAP_PAIR = '__';
public $line;
public function __construct($length)
{
$this->line = str_pad('', $length, self::STONE_PAIR);
}
// Removes a pair of stones from the line at nth location.
public function remove($n)
{
if(substr($this->line, $n-1, 2) == self::STONE_PAIR)
$this->line =
substr_replace($this->line, self::GAP_PAIR , $n-1, 2);
else
throw new Exception('Invalid move.');
}
// Check if there are no further possible moves.
public function is_finished()
{
return strpos($this->line, self::STONE_PAIR) === false;
}
// Representation of line.
public function __toString()
{
return implode('.', str_split($this->line)) ."\n";
}
};
$game = new GameOfStones(6);
echo $game;
var_dump($game->is_finished());
$game->remove(5);
echo $game;
var_dump($game->is_finished());
$game->remove(2);
echo $game;
var_dump($game->is_finished());
Output:
O.O.O.O.O.O
bool(false)
O.O.O.O._._
bool(false)
O._._.O._._
bool(true)
Currently this class starts by making a line which is a string of 'O' characters.
So if the length was 5, the line would be a string like this:
OOOOO
The remove method takes an index. If that index was 1, first the line is checked at the string's 0 index (your n-1) for two consecutive O's. In other words 'are there stones to remove at a given position?'. If there are stones, we do a string replacement at that position, and swap the two Os for two _s.
The is_finished method checks the line for the first occurance of two Os. In other words if there are two consecutive stones there is still a move on the line to play.
The magic method __toString, is the string representation of a GameOfStones object. That's used as a way to visualise the state of the game.
O.O.O.O._._
The above shows four stones and two gaps (I'm not sure if the dot separators are necessary - the underscores can bleed into each other that's why I've used them).
I have added example use of the code, where (two) pairs of stones are removed from a line of six stones. After each removal we check if there is another possible move, or rather if the game has ended.
There is no player attribution currently, that's left to you.
Your last rule:
'If the number of stone left is odd, A wins. Otherwise, B wins.'
I am struggling with. See these examples:
i) Line of length 3:
OOO
O__ A (1)
End: one (odd) stone left.
ii) Line of length 4:
OOOO
OO__ A (3)
____ B (1)
End: zero (even) stones left.
ii) Line of length 7:
OOOOOOO
O__OOOO A(1)
O__O__O B(5)
End: three (odd) stones left.
I'd say that the person that removes the pair so the next player can't go is the winner. In game ii) above if A had played at position 1 (O__O), then they would prevent B from playing.
Related
I have a two column layout with this disposition of elements:
A B
B A
A B
B A
…
A and B elements have content from different origins and also different styles. So, I'm trying to find an expression to generate this A B B A A B B A … sequence both in PHP and CSS nth-child.
This is what I'm doing to generate the layout:
/* $post_ids is an Array of ID's */
$count = count( $post_ids );
for ( $i = 0; $i < $count; $i++ ) {
$classes = ['teaser', 'lg-6', 'md-6', 'sm-12'];
if ( ( 2 * $i ) % 2 == 0 ) { // This is wrong. Always true!
$classes[] = 'a-element';
} else {
$classes[] = 'b-element';
}
insert_post( $post_ids[ $i ], $classes ); // This is a custom function
}
And this is my CSS:
.teaser:nth-child(2n) { // Also wrong
/* Styles for A items */
}
I know once I got the correct PHP sequence I could replace my CSS with:
.a-element {…}
.b-element {…}
But I'd like to know if this could be also done with nth-child...
I guess it can't be that hard, but I'm kinda stuck with this... Any hint or help will be much appreciated!
Edit: After #axiac's answer and some research, I've learned that nth-child only allows:
a number - any positive integer (1,2,3,20, etc.)
a keyword - even or odd
an expression - in the form of an+b (a, b being integers)
So, I guess what I want can't be done with CSS's nth-child. Thank you guys!
The PHP code you need is:
if ((int)(($i + 1) / 2) % 2 == 0 ) {
$classes[] = 'a-element';
} else {
$classes[] = 'b-element';
}
Update
At OP's request, this is how I produced the code above. The desired outcome is:
A B B A A B B A ..
after the initial A each symbol repeats twice. We use a for (;;) loop to iterate from 0 to some $n greater than zero;
the alternation is provided by the modulo operation (% 2);
grouping the values can be done by finding a common property for consecutive numbers. The integer result of division by the desired group size is such a property. If you need to output 5 As followed by 5 Bs then you just notice that any positive integer number can be written as 5 * k + r where r is one of 0, 1, 2, 3, 4 (this is how the division of integer numbers works). There are exactly 5 consecutive integer numbers that divided by 5 produce the same integer result (and different remainders);
given that the PHP division always produce real numbers, the conversion of the result to int (by type casting the result to (int)) is needed;
the + 1 offset is needed to "push" one A before the first 2 Bs. 0 and 1 produce the same result (0) when divided by 2 (they make the first group), 2 and 3 produce 1 and make the second group and so on.
Generalization
If you need to produce N different types of blocks (A, B, C, D a.s.o.), each of them appear M consecutive times (A A A B B B C C C D D D ..., M is 3 here) then the formula is:
(int)(($i + $k) / M) % N
The value produced by this formula is one of 0, 1 ... N - 1 and it tells what symbol to use (A, B a.s.o.). Without + $k this formula generates M instances of A followed by M instances of B, M instances of C and so on until the last symbol. It prints M * N symbols in total then it starts over with A.
The value of $k is one of 0 .. M * N - 1 and it allows the sequence to start from any point inside the sequence. It represents the number of symbols to skip from the start of the sequence.
If I understand correctly the problem is with:
(2 * $i) % 2 == 0
this will return true for all iterations (2 * $i) is always even
try:
$i % 2 == 0
instead
I want a hint on a efficient algorithm of solving the following:
(Okay, The question was not that, I just made this for simplicity).
Example: Out of N Advert boards there should be M advert of a company in K consecutive boards. and the Adverts will be used such a way that only MINIMUM number of Adverts will be used
if N=3,K=2,M=1. The answer will be one 010;
if N=6, K=3, M=2 the answer will be 6.
011011,
011101,
011110,
101101,
101110,
110110.
I took the approach of Creating all the combinations(with binary approach) with iterative and recursive method.After that I filtered it. It is working well except if N is big it will crash.(as expected). So Is there any efficient method of solving these?
I just took another approach but it is not going to well .. :(
Second approach
if($n%$k == 0){
$perm = $m*($n/$k);
}else{
$perm = $m*ceil($n/$k);
}
Then I will do the nCr... and now I'm lost
First Approach
<?php
$n = $input1;$k = $input2;$l=$input3; $total = 0;
$flag = false;$arrays = array();$z=0;$min=$n;$x=0;
$total_permutations = pow(2,$n);
for($i=0;$i<$total_permutations;$i++){
$binary = base_convert($i, 10, 2);
$binary = str_pad($binary, $n,"0", STR_PAD_LEFT);
for($j=0;$j<=($n-$k);$j++){
$flag = false;$x=0;
for($m=0;$m<$k;$m++){
$x += intval($binary{$j+$m});
}
if($x<$l){
$flag = true;
break;
}
}
if(!$flag){
$arrays[$z]=str_split($binary);
$arrays[$z] = array_map('intval', $arrays[$z]);
$z++;
echo $binary."<br />";
}
unset($binary);
}
$min = min(array_map('array_sum',$arrays));
echo "------------<br />";
foreach($arrays as $val){
$sum = array_sum($val);
if($sum == $min){
echo implode("",$val);echo "<br>";
$total++;
}
}
return $total;
}
?>
To elaborate on my comment, here is one potential solution (Though, I would be very disappointed if there wasn't a better one)
1) First, calculate the minimum number of 1's needed in a valid solution. (I believe this is simply max(M, floor(n/k)*m + max(0, n%k-(k-m))). The formula is derived from building a string one letter at a time, placing 0's whenever possible)
2) Now, assume N > K (otherwise the answer is trivial).
We define the sub-problem to be: "Given a prefix P of length K, and a budget B of 1's to place, how many ways are there to fill out N characters whilst still enforcing the M rule?"
For example, consider that our string is "101XXXXXX", with K = 3, M = 2, and B = 4. Here, N = 6, P = "101". We solve this sub-problem like so:
a) Check if the budget is big enough in O(N) time. Return 0 if it isn't
If N=0, return 1 trivially
b) Set total possible solutions to 0
c) Set the first unknown character to 1. Compute the new prefix P'
(by stripping off the first character, and adding a "1" to the end),
the new B' = B-1, the new N' = N-1, and solve the new sub-problem:
Add its result to our total
d) Set the unknown character to 0 instead: But only if the new prefix P'
(strip, add "0") has at least M 1's. If so, set B' = B-1, N' = N-1,
and solve the new sub-problem. Add its result to our total
e) Return the total
To solve the original problem, simply consider all possible prefixes P (all nCr(K,M) of them), and sum up the solutions to the derived sub-problems. By caching the results to sub-problems based on unique inputs P, N, and B, we reduce the amount of duplicate work drastically. Amortized analysis should show that the full solution runs in O(N*nCr(K,M)) time
*I try to count the unique appearances of a substring inside a list of words *
So check the list of words and detect if in any words there are substrings based on min characters that occur multiple times and count them. I don't know any substrings.
This is a working solution where you know the substring but what if you do not know ?
Theres a Minimum Character count where words are based on.
Will find all the words where "Book" is a substring of the word. With below php function.
Wanted outcome instad:
book count (5)
stor count (2)
Given a string of length 100
book bookstore bookworm booking book cooking boring bookingservice.... ok
0123456789... ... 100
your algorithm could be:
Investigate substrings from different starting points and substring lengths.
You take all substrings starting from 0 with a length from 1-100, so: 0-1, 0-2, 0-3,... and see if any of those substrings accurs more than once in the overall string.
Progress through the string by starting at increasing positions, searching all substrings starting from 1, i.e. 1-2, 1-3, 1-4,... and so on until you reach 99-100.
Keep a table of all substrings and their number of occurances and you can sort them.
You can optimize by specifying a minimum and maximum length, which reduces your number of searches and hit accuracy quite dramatically. Additionally, once you find a substring save them in a array of searched substrings. If you encounter the substring again, skip it. (i.e. hits for book that you already counted you should not count again when you hit the next booksubstring). Furthermore you will never have to search strings that are longer than half of the total string.
For the example string you might run additional test for the uniquness of a string.
You'd have
o x ..
oo x 7
bo x 7
ok x 6
book x 5
booking x 2
bookingservice x 1
with disregarding stings shorter than 3 (and longer than half of total textstring), you'd get
book x 5
booking x 2
bookingservice x 1
which is already quite a plausible result.
[edit] This would obviously look through all of the string, not just natural words.
[edit] Normally I don't like writing code for OPs, but in this case I got a bit interested myself:
$string = "book bookshelf booking foobar bar booking ";
$string .= "selfservice bookingservice cooking";
function search($string, $min = 4, $max = 16, $threshhold = 2) {
echo "<pre><br/>";
echo "searching <em>'$string'</em> for string occurances ";
echo "of length $min - $max: <br/>";
$hits = array();
$foundStrings = array();
// no string longer than half of the total string will be found twice
if ($max > strlen($string) / 2) {
$max = strlen($string);
}
// examin substrings:
// start from 0, 1, 2...
for ($start = 0; $start < $max; $start++) {
// and string length 1, 2, 3, ... $max
for ($length = $min; $length < strlen($string); $length++) {
// get the substring in question,
// but search for natural words (trim)
$substring = trim(substr($string, $start, $length));
// if substring was not counted yet,
// add the found count to the hits
if (!in_array($substring, $foundStrings)) {
preg_match_all("/$substring/i", $string, $matches);
$hits[$substring] = count($matches[0]);
}
}
}
// sort the hits array desc by number of hits
arsort($hits);
// remove substring hits with hits less that threshhold
foreach ($hits as $substring => $count) {
if ($count < $threshhold) {
unset($hits[$substring]);
}
}
print_r($hits);
}
search($string);
?>
The comments and variable names should make the code explain itself. $string would come for a read file in your case. This exmaple would output:
searching 'book bookshelf booking foobar bar booking selfservice
bookingservice cooking' for string occurances of length 4 - 16:
Array
(
[ook] => 6
[book] => 5
[boo] => 5
[bookin] => 3
[booking] => 3
[booki] => 3
[elf] => 2
)
Let me know how you implement it :)
This is my first approximation: unfinished, untested, has at least 1 bug, and is written in eiffel. Well I am not going to do all the work for you.
deferred class
SUBSTRING_COUNT
feature
threshold : INTEGER_32 =5
biggest_starting_substring_length(a,b:STRING):INTEGER_32
deferred
end
biggest_starting_substring(a,b:STRING):STRING
do
Result := a.substring(0,biggest_starting_substring_length(a,b))
end
make_list_of_substrings(a,b:STRING)
local
index:INTEGER_32
this_one: STRING
do
from
a_index := b_index + 1
invariant
a_index >=0 and a_index <= a.count
until
a_index >= a.count
loop
this_one := biggest_starting_substring(a.substring (a_index, a.count-1),b)
if this_one.count > threshold then
list.extend (this_one)
end
variant
a.count - a_index
end
end -- biggest_substring
list : ARRAYED_LIST[STRING]
end
There is a problem in Interview Street challange. Maybe the most easiest of all challenges. "Unfriendly Numbers", is the name and question goes like this.
There is one friendly number and N unfriendly numbers. We want to find how many numbers are there which exactly divide the friendly number, but does not divide any of the unfriendly numbers.
Input Format:
The first line of input contains two numbers N and K seperated by spaces. N is the number of unfriendly numbers, K is the friendly number.
The second line of input contains N space separated unfriendly numbers.
Output Format:
Output the answer in a single line.
I did a PHP programming like this:
<?php
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
$handle = fopen ("php://stdin","r");
$input = fgets($handle);
$num_unfriendly_number=substr($input,0,1);
$friendly_number=substr($input,2,1);
$input2=fgets($handle);
for($i=0;$i<=($num_unfriendly_number); $i=$i+2){
$unfriendly_numbers[$i]=substr($input2,$i,1);
}
//truncates additional input
//now getting divisiors of given friendly numbers
$check_num=1;
//one is always a divisor of any number
$divisior[0]=1;
$arrayindex=1;
for($check_num; $check_num<=$friendly_number; $check_num++){
$hold_var=$friendly_number%$check_num;
if($hold_var==0){
$divisor[$arrayindex]=$check_num;
$arrayindex++;
}
}
$index=0;
foreach($divisor as $test_div){
$output=true;
foreach($unfriendly_numbers as $test_unfrnd){
if($test_unfrnd%$test_div){
$output=false;
}
}
if ($output){
$outputarray[$index]=$test_div;
$index++; //edited afterwards after #Boris's suggestion but didn't work :(
}
}
$num_of_output=count($outputarray);
define('STDOUT',fopen("php://stout","r"));
fwrite(STDOUT,$num_of_output);
?>
The above programme worked fine for 2 testcases but did not applied for other tests. I did some research but did not found any errors. Any helps please. Thanks in advance.
Fist of all I would like to mention that I do not know php. However, I think this is simple enough I can try to help.
Several errors I see:
for($i=0;$i<=($num_unfriendly_number); $i=$i+2){
$unfriendly_numbers[$i]=substr($input2,$i,1);
}
Here you use substr($input2,$i,1);, this however assumes all your unfriendly numbers are digits, which might not always be the case. Better use the split function in php. Replace the whole while with the following:
$unfriendly_numbers = explode(" ", $input2);
After that:
$index=0;
foreach($divisor as $test_div){
$output=true;
foreach($unfriendly_numbers as $test_unfrnd){
if($test_unfrnd%$test_div){
$output=false;
}
}
if ($output){
$outputarray[$index]=$test_div;
}
}
Here you never increase the $index variable. Isn't this meaning that you will override the divisors one with other? USe the operator []=. It appends to an array in php:
if ($output){
$outputarray []= $test_div;
}
EDIT One more error I see is that you count on the friendly number to be a digit too. You can fix this too:
$friendly_number=substr($input,2,1);
->
$friendly_number=explode(" ", $input)[0];
I have the same problem I can't understand why this code can't finish in less than 16 seconds!
I would like to hear your tricks
a = raw_input()# this will read this line: 8 16
b = raw_input()# this will read this line: 2 5 7 4 3 8 3 18
al = a.split()
bl = b.split()
blint = []
fn = int(al[1])
fnlist = [fn]
half_fn = fn / 2 # only I go to half the number to save some time
k = 1
while k <= half_fn:
if fn % k == 0:
fnlist.append(k)
k += 1
plist = []
for j in bl:
blint.append(int(j)) # here I changed the bl list elements which are string to int
for i in fnlist:
for j in blint: #I have the int elements so I don't need every time bring the string and change it to int
if j % i == 0:
plist.append(i)
break
counter = len(fnlist) - len(plist)
print counter
Not a duplicate of-
optimal algorithm for finding unique divisors
I came across this problem. I am not able to find an optimal algorithm.
The problem is :
Given a list L of natural numbers(number can be really large) and a number N, what's the optimal algorithm to determine the number of divisors of N which doesn't not divide any of the numbers present in the list L. Numbers in the list can be repetitive ie, one number can occur more than once.
Observation:
Divisors of some divisor d of N are also divisors of N.
MY approach was :
Find the divisors of N.
Sort L in reverse order(largest element being 1st element).
foreach divisor d of N, I check whether it divides any element in the list or not.(stop when you come to check for an element less than d in the list, as the list is sorted)
If d divides some number in the list L, then I don't check for any divisor of d, that is, I skip this checking.
Ultimately, left divisors which were neither divided any number in the list nor skipped are counted. This count is the final answer.
But this algorithm is not optimal for this problem.
Any ideas for a better algorithm?
What you need to look into is : co-primes (or relatively primes)
In number theory, a branch of mathematics, two integers a and b are
said to be coprime (also spelled co-prime) or relatively prime if the
only positive integer that evenly divides both of them is 1.
So to "transcode" your problem :
You basically want to find the Number of coprimes of N from the L list.
When a and b are co-primes?
If two numbers are relatively prime then their greatest common divisor (GCD)
is 1
Example code (for GCD) in PHP :
<?php
$gcd = gmp_gcd("12", "21");
echo gmp_strval($gcd) . "\n";
?>
Simply put :
$count = 0
Foreach element e in list L : calculate the GCD(e,N)
Is their GCD=1? If yes, they are coprime (so N and e have no common divisors). Count it up. $count++
And that's all there is to it.
First, factorize n and represent it in the following way: p1:k1, p2:k2,..., pm:km such that p1,p2,... are all primes and n=p1^k1 * p2^k2 ....
Now, iterate over r1, r2, r3,..., rm such that r1<=k1, r2<=k2, ..., rm<=km and check if p1^r1*p2^r2...*pm^rm divides any number in L. If not increment count by 1.
Optimization: Pick a value for r1. See if p1^r1 divides any number in L. If yes, then pick a number for r2 and so on. If p1^r1 does not divide any number in L, then increment count by (k2+1)(k3+1)..*(km+1).
Example N=72, L=[4, 5, 9, 12, 15, 20]:
Writing N as a primal product: 2:3, 3:2 (2^3*3*2 = 72).
p1=2, p2=3, k1=3, k2=2
count=0
r1=0:
r2=0:
Divides 4
r1=0:
r2=1:
Divides 9
r1=0:
r2=2:
Divides 9
r1=1:
r2=0:
Divides 4
r1=1:
r2=1:
Divides 12
r1=1:
r2=2:
L not divisible by 18. Count+=1 = 1
r1=2:
r2=0:
Divides 4
r1=2:
r2=1:
Divides 12
r1=2:
r2=2:
L not divisible by 36. Count+=1 = 2
r1=3:
r2=0:
L not divisible by 8. Count+=(k2+1) +=(2+1) = 5
<?php
class Divisors {
public $factor = array();
public function __construct($num) {
$this->num = $num;
}
// count number of divisors of a number
public function countDivisors() {
if ($this->num == 1) return 1;
$this->_primefactors();
$array_primes = array_count_values($this->factor);
$divisors = 1;
foreach($array_primes as $power) {
$divisors *= ++$power;
}
return $divisors;
}
// prime factors decomposer
private function _primefactors() {
$this->factor = array();
$run = true;
while($run && #$this->factor[0] != $this->num) {
$run = $this->_getFactors();
}
}
// get all factors of the number
private function _getFactors() {
if($this->num == 1) {
return ;
}
$root = ceil(sqrt($this->num)) + 1;
$i = 2;
while($i <= $root) {
if($this->num % $i == 0) {
$this->factor[] = $i;
$this->num = $this->num / $i;
return true;
}
$i++;
}
$this->factor[] = $this->num;
return false;
}
} // our class ends here
$example = new Divisors(4567893421);
print $example->countDivisors();
?>