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
Related
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.
I have a following array (php):
[
[id=>1,weight=]
[id=>2,weight=]
[id=>3,weight=]
[id=>4,weight=]
]
I need to create all possible versions of this array asigning 0-100 weight to each item['weight'] with a step of N.
I don't know how this type of problems are called. It is NOT permutation/combination.
Lets say N is 10, I am aiming to get:
[
[
[id=>1,weight=10]
[id=>2,weight=10]
[id=>3,weight=10]
[id=>4,weight=70]
]
[
[id=>1,weight=10]
[id=>2,weight=10]
[id=>3,weight=20]
[id=>4,weight=60]
]
[
[id=>1,weight=10]
[id=>2,weight=10]
[id=>3,weight=30]
[id=>4,weight=50]
]
[
[id=>1,weight=10]
[id=>2,weight=10]
[id=>3,weight=40]
[id=>4,weight=40]
]
...all possible combination of weights for id=x.
[
[id=>1,weight=70]
[id=>2,weight=10]
[id=>3,weight=10]
[id=>4,weight=10]
]
]
Sum of 4 item['weights'] in array on same level is always 100 (or 0.1). And inside parent array I've all possible combinations of weights from 10-100 for id=x.
This problem is sometimes described as allocating identical balls into distinct bins. You didn't specify your problem exactly, so I'll take a guess here but the logic will be identical.
I'll assume you're distributing b = N/step balls into 4 bins.
Think of the balls all in a row, and then using 3 bars to separate the balls into 4 bins:
*|||*****.
If N=10 and you're distributing 100 points, the above example is the same is 30, 20, 0, 50. If zeroes aren't allowed, you can reduce the amount you're distributing by 4*b and assume each bin starts out with N/step in it (so you're distributing the leftover points).
The number of ways to do this is choose(balls + bins - 1, bins - 1).
Theres probably a better way, but heres my attempt:
$result=array(); // Empty array for your result
$array=range(1117,7777); // Make an array with every number between 1117 and 7777
foreach ($array as $k=>$v) { // Loop through numbers
if ((preg_match('/[890]/',$v) === 0) && (array_sum(str_split($v, 1)) === 10)) {
// If number does not contain 8,9 or 0 and sum of all 4 numbers is 10
// Apply function to multiply each number by 10 and add to result array
$result[] = array_map("magnitude", str_split($v, 1));
}
}
function magnitude($val) { // function to multiply by 10 for array map
return($val * 10);
}
print_r($result);
Working demo here
EDIT
Sorry I realised my code explanation isn't totally clear and I condensed it all a bit too much to make it easy to follow.
In your example the first array would contain (10,10,10,70). For the sake of simplicity I divided everything by 10 for the calculations and then just multiplied by 10 once I had a result, so your array of (10,10,10,70) becomes (1,1,1,7). Then your final array would be (70,10,10,10) which would become (7,1,1,1).
My approach was to first to create an array containing every combination of these four numbers, which I did in two steps.
This line $array=range(1117,7777); creates an array like this (1117, 1118, 1119 ... 7775, 7776, 7777) (My number range should really have been 1117 - 7111 instead of 1117-7777).
Applying str_split($v, 1) to each value in the loop splits each 4 digit number in the array into another array conatining 4 single digit numbers, so 1117 will become (1, 1, 1, 7) etc
As each of your items can't have a weight below 10 or above 70 we use (preg_match('/[890]/',$v) === 0) to skip any arrays which have 0,8 or 9 in them anywhere, then array_sum(str_split($v, 1)) === 10) adds up the four digits in the array and only returns arrays which total 10 (you wanted ones which total 100, but I divided by 10 earlier).
array_map applies a function to each element in an array. In my example the function multiplies each value by 10, to undo the fact I divided by 10 earlier.
When you say is it possible to alter steps, can you give me a couple of examples of other values and the output you want for them?
If you want a totally different approach and using mysql isn't a problem then this also works:
Create a new table with a single row. Insert all the values you need to check
INSERT INTO `numbers` (`number`) VALUES
(10),
(20),
(30),
(40),
(50),
(60),
(70);
Then your php looks like this
$result=array();
try {
$dbh = new PDO('mysql:host=aaaaa;dbname=bbb', 'ccc', 'dddd');
foreach($dbh->query('SELECT *
FROM numbers a
CROSS JOIN // A cross join returns the cartesian product of rows
numbers b // so every row with every combination of the other rows
CROSS JOIN
numbers c
CROSS JOIN
numbers d
ON
a.number = b.number OR a.number != b.number') as $row) {
if (($row[0] + $row[1] + $row[2] + $row[3]) === 100) {
$result[] = $row;
}
}
$dbh = null;
} catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
print_r($result);
Not quite sure what to set this title as, or what to even search for. So I'll just ask the question and hope I don't get too many downvotes.
I'm trying to find the easiest way to find the highest possible number based on two fixed numbers.
For example:
The most I can multiply by is, say, 18 (first number). But not going over the resulted number, say 100 (second number).
2 x 18 = 36
5 x 18 = 90
But if the first number is a higher number, the second number would need to be less than 18, like so:
11 x 9 = 99
16 x 6 = 96
Here I would go with 11, because even though the second number is only 9, the outcome is the highest. The second number could be anything as long as it's 18 or lower. The first number can be anything, as long as the answer remains below 100. Get what I mean?
So my question is, how would write this in php without having to use switches, if/then statements, or a bunch of loops? Is there some math operator I don't know about that handles this sort of thing?
Thanks.
Edit:
The code that I use now is:
function doMath($cost, $max, $multiplier) {
do {
$temp = $cost * $multiplier;
if ($temp > $max) { --$multiplier; }
} while ($temp > $max);
return array($cost, $temp, $multiplier);
}
If we look at the 11 * 9 = 99 example,
$result = doMath(11, 100, 18);
Would return,
$cost = 11, $temp = 99, $multiplier = 9
Was hoping there was an easier way so that I wouldn't need to use a loop, being as how there are a lot of numbers I need to check.
If I understood you right, you are looking for the floor function, combining it with the min function.
Both a bigger number c and a smaller number a are part of the problem, and you want to find a number b in the range [0, m] such that a * b is maximal while staying smaller (strictly) than c.
In your example, 100/18 = 5.55555, so that means that 18*5 is smaller than 100, and 18*6 is bigger than 100.
Since floor gets you the integral part of a floating point number, $b = floor($c/$a) does what you want. When a divides c (that is, c/a is an integer already), you get a * b == c.
Now b may be outside of [0,m] so we want to take the smallest of b and m :
if b is bigger than m, we are limited by m,
and if m is bigger than b, we are limited by a * b <= c.
So in the end, your function should be :
function doMath($cost, $max, $multiplier)
{
$div = min($multiplier, floor($max/$cost));
return array($cost, $div * $cost, $div);
}
I am not good with math and I can't wrap my head around this, I want to generate EVERY possible 3 positive numbers there is that sum to N example 100, for instance:
0 - 0 - 100
0 - 1 - 99
1 - 1 - 98
You don't need to answer me with PHP code, just a general idea on how I can generate those numbers would be sufficient.
Thanks.
Brute force is an option in your case: you can just use 2 nested loops
and it takes less than 10000 tests only.
// pseudo code
for (i = 0; i <= 100; ++i)
for (j = 0; j <= 100; ++j) {
if ((i + j) > 100)
break;
k = 100 - i - j;
print(i, j, k);
}
If duplicates e.g. 0, 0, 100 and 0, 100, 0 should be excluded, you can use slightly modified code:
// pseudo code
for (i = 0; i <= 100; ++i)
for (j = i; j <= 100; ++j) {
if ((i + j) > 100)
break;
k = 100 - i - j;
if (j <= k)
print(i, j, k);
}
As for just an algorithm, consider first just pairs of numbers whose sum are less than or equal to 100. These should be easy to list. I.e
0 1 2 100
{{0,0}, {0,1}, {0,2},.........., {0,100}
{1,1}, {1,2},..., {1,99}
.
.
...............................{50,50}}
But then each of those pairs, taking their sums can also be paired with precisely one number such that the entire triplet sum is 100.
So to summarize; if you could make first a list of these pairs (would require a double loop i in [0,100], j in [0:50]); and then loop through all pairs in this list calculating the third number you should get all triplets without duplication. Furthermore, if done correctly you wouldn't actually need any lists at all, with proper loop indexing you could calculate them in position.
edit Noticed you wanted duplicates - (though you could permute each triplet).
another approach with slightly better time complexity.
n=int(input())
for i in range(0,int(n/2+1)):
for j in range(0,int(i/2+1)):
print(j," ",i-j," ",(int)(n-i))
l=n-i
for j in range(0,int((n-i)/2+1)):
print(j," ",l-j," ",(int)(i))
it is just the extension of this algorithm which produces two numbers whose sum is equal to n
n=int(input())
for i in range(0,int(n/2+1)):
print(i," ",n-i)
I see you need those duplicates also just change the limits to full in line number 2,3 and 6
n=int(input())
for i in range(0,n):
for j in range(0,i):
print(j," ",i-j," ",(int)(n-i))
l=n-i
for j in range(0,l):
print(j," ",l-j," ",(int)(i))
I am doing this programming challenge which can be found at www.interviewstreet.com (its the first challenge worth 30 points).
When I submitted the solution, I was returned a result which said that the answer was wrong because it only passed 1/11 test cases. However, I feel have tested various cases and do not understand what I am doing wrong. It would be helpful to know what those test cases could be so that I can test my program.
Here is the question (in between the grey lines below):
Quadrant Queries (30 points)
There are N points in the plane. The ith point has coordinates (xi, yi). Perform the following queries:
1) Reflect all points between point i and j both including along the X axis. This query is represented as "X i j"
2) Reflect all points between point i and j both including along the Y axis. This query is represented as "Y i j"
3) Count how many points between point i and j both including lie in each of the 4 quadrants. This query is represented as "C i j"
Input:
The first line contains N, the number of points. N lines follow.
The ith line contains xi and yi separated by a space.
The next line contains Q the number of queries. The next Q lines contain one query each, of one of the above forms.
All indices are 1 indexed.
Output:
Output one line for each query of the type "C i j". The corresponding line contains 4 integers; the number of points having indices in the range [i..j] in the 1st,2nd,3rd and 4th quadrants respectively.
Constraints:
1 <= N <= 100000
1 <= Q <= 100000
You may assume that no point lies on the X or the Y axis.
All (xi,yi) will fit in a 32-bit signed integer
In all queries, 1 <=i <=j <=N
Sample Input:
4
1 1
-1 1
-1 -1
1 -1
5
C 1 4
X 2 4
C 3 4
Y 1 2
C 1 3
Sample Output:
1 1 1 1
1 1 0 0
0 2 0 1
Explanation:
When a query says "X i j", it means that take all the points between indices i and j both including and reflect those points along the X axis. The i and j here have nothing to do with the co-ordinates of the points. They are the indices. i refers to point i and j refers to point j
'C 1 4' asks you to 'Consider the set of points having index in {1,2,3,4}. Amongst those points, how many of them lie in the 1st,2nd,3rd and 4th quads respectively?'
The answer to this is clearly 1 1 1 1.
Next we reflect the points between indices '2 4' along the X axis. So the new coordinates are :
1 1
-1 -1
-1 1
1 1
Now 'C 3 4' is 'Consider the set of points having index in {3,4}. Amongst those points, how many of them lie in the 1st,2nd,3rd and 4th quads respectively?' Point 3 lies in quadrant 2 and point 4 lies in quadrant 1.
So the answer is 1 1 0 0
I'm coding in PHP and the method for testing is with STDIN and STDOUT.
Any ideas on difficult test cases to test my code with? I don't understand why I am failing 10 / 11 test cases.
Also, here is my code if you're interested:
// The global variable that will be changed
$points = array();
/******** Functions ********/
// This function returns the number of points in each quadrant.
function C($beg, $end) {
// $quad_count is a local array and not global as this gets reset for every C operation
$quad_count = array("I" => 0, "II" => 0, "III" => 0, "IV" => 0);
for($i=$beg; $i<$end+1; $i++) {
$quad = checkquad($i);
$quad_count[$quad]++;
}
return $quad_count["I"]." ".$quad_count["II"]." ".$quad_count["III"]." ".$quad_count["IV"];
}
// Reflecting over the x-axis means taking the negative value of y for all given points
function X($beg, $end) {
global $points;
for($i=$beg; $i<$end+1; $i++) {
$points[$i]["y"] = -1*($points[$i]["y"]);
}
}
// Reflecting over the y-axis means taking the negative value of x for all given points
function Y($beg, $end) {
global $points;
for($i=$beg; $i<$end+1; $i++) {
$points[$i]["x"] = -1*($points[$i]["x"]);
}
}
// Determines which quadrant a given point is in
function checkquad($i) {
global $points;
$x = $points[$i]["x"];
$y = $points[$i]["y"];
if ($x > 0) {
if ($y > 0) {
return "I";
} else {
return "IV";
}
} else {
if ($y > 0) {
return "II";
} else {
return "III";
}
}
}
// First, retrieve the number of points that will be provided. Make sure to check constraints.
$no_points = intval(fgets(STDIN));
if ($no_points > 100000) {
fwrite(STDOUT, "The number of points cannot be greater than 100,000!\n");
exit;
}
// Remember the points are 1 indexed so begin key from 1. Store all provided points in array format.
for($i=1; $i<$no_points+1; $i++) {
global $points;
list($x, $y) = explode(" ",fgets(STDIN)); // Get the string returned from the command line and convert to an array
$points[$i]["x"] = intval($x);
$points[$i]["y"] = intval($y);
}
// Retrieve the number of operations that will be provied. Make sure to check constraints.
$no_operations = intval(fgets(STDIN));
if($no_operations > 100000) {
fwrite(STDOUT, "The number of operations cannot be greater than 100,000!\n");
exit;
}
// Retrieve the operations, determine the type and send to the appropriate functions. Make sure i <= j.
for($i=0; $i<$no_operations; $i++) {
$operation = explode(" ",fgets(STDIN));
$type = $operation[0];
if($operation[1] > $operation[2]) {
fwrite(STDOUT, "Point j must be further in the sequence than point i!\n");
exit;
}
switch ($type) {
case "C":
$output[$i] = C($operation[1], $operation[2]);
break;
case "X":
X($operation[1], $operation[2]);
break;
case "Y":
Y($operation[1], $operation[2]);
break;
default:
$output[$i] = "Sorry, but we do not recognize this operation. Please try again!";
}
}
// Print the output as a string
foreach($output as $line) {
fwrite(STDOUT, $line."\n");
}
UPDATE:
I finally found a test case for which my program fails. Now I am trying to determine why. This is a good lesson on testing with large numbers.
10
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
12
C 1 10
X 1 3
C 5 5
Y 2 10
C 10 10
C 1 10
X 1 3
C 5 5
Y 2 10
C 10 10
X 3 7
C 9 9
I am going to test this properly by initializing an error array and determining which operations are causing an issue.
I discovered a test case that failed and understood why. I am posting this answer here so it's clear to everyone.
I placed a constraint on the program so that j must be greater than i, otherwise an error should be returned. I noticed an error with the following test case:
10
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1 1
1
C 2 10
The error returned for the operation C. Essentially the program believed that "2" was greater than "10". The reason for this I discovered was the following:
When using fgets(), a string is returned. If you perform string operations such as explode() or substr() on that line, you are converting the numbers in that initial string into a string again. So this means that the 10 becomes "10" and then after string operations becomes "0".
One solution to this is to use the sscanf() function and basically tell the program to expect a number. Example: for "C 2 10" you could use:
$operation_string = fgets(STDIN);
list($type, $begpoint, $endpoint) = sscanf($operation_string, "%s %d %d");
I submitted the new solution using sscanf() and now have 3/11 test cases passed. It did not check any more test cases because the CPU time limit was exceeded. So, now I have to go back and optimize my algorithm.
Back to work! :)
To answer, "What are those test cases?" Try this "solution":
<?php
$postdata = http_build_query(
array(
'log' => file_get_contents('php://stdin')
)
);
$opts = array('http' =>
array(
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => $postdata
)
);
$context = stream_context_create($opts);
file_get_contents('http://myserver/answer.php', false, $context);
?>
On your server:
<?php
$fp = fopen('/tmp/answers.log', 'a');
fputs($fp, $_POST['log']."\n");
fclose($fp);
?>
Edit:
I did that. And came up with this being your main problem (I think):
$operation = explode(" ",fgets(STDIN));
Change that to:
$operation = explode(" ",trim(fgets(STDIN)));
Because otherwise "9" > "41 " due to string comparison. You should make that fix in any place you read a line.
As far as I guess, this solution won't work. Even if you solve the Wrong Answer problem, the solution will time out.
I was able to figure out a way for returning the quadrants count in O(1) time.
But not able to make the reflections in lesser time. :(