Stylus: target lines among a square component items - for-loop

I try to take target stylus lines of a square made up of divs.
I tried unsuccessfully with a for loop because I have trouble understanding the principle.
To illustrate the problem, here is a code for which I seek to number each item with the current line number:
sqrt(x)
return math(x, 'sqrt')
$n = 100 // Items
$rn = sqrt($n)
$length = 1...($n + 1)
for $i in $length
if ($i < ($rn + 1))
$col = '' + L1 + ''
else if ($i < (($rn * 2) + 1))
$col = '' + L2 + ''
else if ($i < (($rn * 3) + 1))
$col = '' + L3 + ''
// etc...
else
$col = '' + L0 + '' // Feedback
screen :nth-child({$i})::after
content $col
Example online.
For now I target the line with condition if / else, but it is not satisfactory because I want to focus my lines without knowing in advance the number of ...
How to proceed ?

It's good I found. Here optimized code:
sqrt(x)
return math(x, 'sqrt')
$n = 100 // Items
$rn = sqrt($n)
$length = 1...($n + 1)
for $i in $length
screen :nth-child({$i})::after
$col = '' + 'L' + (floor(($i - 1) / $rn) + 1) + ''
content $col
Example online 1
Example online 2

Related

Cutting algorithm of two dimensional board

I have problem with my homework.
Given a board of dimensions m x n is given, cut this board into rectangular pieces with the best total price. A matrix gives the price for each possible board size up through the original, uncut board.
Consider a 2 x 2 board with the price matrix:
3 4
3 6
We have a constant cost for each cutting for example 1.
Piece of length 1 x 1 is worth 3.
Horizontal piece of length 1 x 2 is worth 4.
Vertical piece of length 1 x 2 is worth 3.
Whole board is worth 6.
For this example, the optimal profit is 9, because we cut board into 1 x 1 pieces. Each piece is worth 3 and we done a 3 cut, so 4 x 3 - 3 x 1 = 9.
Second example:
1 2
3 4
Now I have to consider all the solutions:
4 1x1 pieces is worth 4x1 - (cost of cutting) 3x1 = 1
2 horizontal 1x2 is worth 2x2 - (cost of cutting) 1x1 = 3
2 vertical 1x2 is worth 3x2 - (cost of cutting) 1x1 = 5 -> best optimal profit
1 horizontal 1x2 + 2 x (1x1) pieces is worth 2 + 2 - (cost of cutting) 2 = 2
1 vertical 1x2 + 2 x (1x1) pieces is worth 3 + 2 - (cost of cutting) 2 = 3
I've read a lot about rod cutting algorithm but I don't have any idea how to bite this problem.
Do you have any ideas?
I did this in Python. The algorithm is
best_val = value of current board
check each horizontal and vertical cut for better value
for cut point <= half the current dimension (if none, return initial value)
recur on the two boards formed
if sum of values > best_val
... best_val = that sum
... record cut point and direction
return result: best_val, cut point, and direction
I'm not sure what you'll want for return values; I gave back the best value and tree of boards. For your second example, this is
(5, [[2, 1], [2, 1]])
Code, with debugging traces (indent and the labeled prints):
indent = ""
indent_len = 3
value = [[1, 2],
[3, 4]]
def best_cut(high, wide):
global indent
print indent, "ENTER", high, wide
indent += " " * indent_len
best_val = value[high-1][wide-1]
print indent, "Default", best_val
cut_vert = None
cut_val = best_val
cut_list = []
# Check horizontal cuts
for h_cut in range(1, 1 + high // 2):
print indent, "H_CUT", h_cut
cut_val1, cut_list1 = best_cut(h_cut, wide)
cut_val2, cut_list2 = best_cut(high - h_cut, wide)
cut_val = cut_val1 + cut_val2
if cut_val > best_val:
cut_list = [cut_list1, cut_list2]
print indent, "NEW H", h_cut, cut_val, cut_list
best_val = cut_val
cut_vert = False
best_h = h_cut
# Check vertical cuts
for v_cut in range(1, 1 + wide // 2):
print indent, "V_CUT", v_cut
cut_val1, cut_list1 = best_cut(high, v_cut)
cut_val2, cut_list2 = best_cut(high, wide - v_cut)
cut_val = cut_val1 + cut_val2
if cut_val > best_val:
cut_list = [cut_list1, cut_list2]
print indent, "NEW V", v_cut, cut_val, cut_list
best_val = cut_val
cut_vert = True
best_v = v_cut
# Return result of best cut
# Remember to subtract the cut cost
if cut_vert is None:
result = best_val , [high, wide]
elif cut_vert:
result = best_val-1, cut_list
else:
result = best_val-1, cut_list
indent = indent[indent_len:]
print indent, "LEAVE", cut_vert, result
return result
print best_cut(2, 2)
Output (profit and cut sizes) for each of the two tests:
(9, [[[1, 1], [1, 1]], [[1, 1], [1, 1]]])
(5, [[2, 1], [2, 1]])
Let f(h,w) represent the best total price achievable for a board with height h and width w with cutting price c. Then
f(h,w) = max(
price_matrix(h, w),
f(i, w) + f(h - i, w) - c,
f(h, j) + f(h, w - j) - c
)
for i = 1 to floor(h / 2)
for j = 1 to floor(w / 2)
Here's a bottom-up example in JavaScript that returns the filled table given the price matrix. The answer would be in the bottom right corner.
function f(prices, cost){
var m = new Array(prices.length);
for (let i=0; i<prices.length; i++)
m[i] = [];
for (let h=0; h<prices.length; h++){
for (let w=0; w<prices[0].length; w++){
m[h][w] = prices[h][w];
if (h == 0 && w == 0)
continue;
for (let i=1; i<(h+1>>1)+1; i++)
m[h][w] = Math.max(
m[h][w],
m[i-1][w] + m[h-i][w] - cost
);
for (let i=1; i<(w+1>>1)+1; i++)
m[h][w] = Math.max(
m[h][w],
m[h][i-1] + m[h][w-i] - cost
);
}
}
return m;
}
$('#submit').click(function(){
let prices = JSON.parse($('#input').val());
let result = f(prices, 1);
let str = result.map(line => JSON.stringify(line)).join('<br>');
$('#output').html(str);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="input">[[3, 4],
[3, 6]]</textarea>
<p><button type="button" id="submit">Submit</button></p>
<div id="output"><div>
Some thoughts on the problem rather than an answer:
It was a long time ago i studied dynamic programming, but i wrote up the following pseudo code which is think is O(n^2):
// 'Board'-class not included
val valueOfBoards: HashMap<Board, int>
fun cutBoard(b: Board, value: int) : int {
if (b.isEmpty()) return 0
if (valueOfBoards[b] > value) {
return 0;
} else {
valueOfBoards[b] = value
}
int maxValue = Integer.MIN_VALUE
for (Board piece : b.getPossiblePieces()) {
val (cuttingCost, smallerBoard) = b.cutOffPiece(piece)
val valueGained: int = piece.getPrice() - cuttingCost
maxValue = Max(maxValue, valueGained + cutBoard(smallerBoard, value + valueGained))
}
return maxValue;
}
The board class is not trivially implemented, here is some elaboration:
// returns all boards which fits in the current board
// for the initial board this will be width*height subboards
board.getPossiblePieces()
// returns a smaller board and the cutting cost of the cut
// I can see this becoming complex, depends on how one chooses to represent the board.
board.cutOffPiece(piece: Board)
It is not clear to me at the moment if cutOffPiece() breaks the algorithm in that you do not know how to optimally cut. I think since the algorithm will proceed from larger pieces to smaller pieces at some point it will be fine.
I tried to solve the re computation of sub problems (identical boards) by storing results in something like HashMap<Board, price> and comparing the new board with the stored best price before proceeding.
According to your answers I've prepared bottom-up and top-down implementation.
Bottom-up:
function bottomUp($high, $wide, $matrix){
$m = [];
for($h = 0; $h < $high; $h++){
for($w = 0; $w < $wide; $w++){
$m[$h][$w] = $matrix[$h][$w];
if($h == 0 && $w == 0){
continue;
}
for($i = 1; $i < ($h + 1 >> 1) + 1; $i++){
$m[$h][$w] = max(
$m[$h][$w],
$m[$i - 1][$w] + $m[$h - $i][$w] - CUT_COST
);
}
for($i = 1; $i < ($w + 1 >> 1) + 1; $i++){
$m[$h][$w] = max(
$m[$h][$w],
$m[$h][$i - 1] + $m[$h][$w - $i] - CUT_COST
);
}
}
}
return $m[$high-1][$wide-1];
}
Top-down:
function getBestCut($high, $wide, $matrix){
global $checked;
if(isset($checked[$high][$wide])){
return $checked[$high][$wide];
}
$bestVal = $matrix[$high-1][$wide-1];
$cutVert = CUT_VERT_NONE;
$cutVal = $bestVal;
$cutList = [];
for($hCut = 1; $hCut < 1 + floor($high/2); $hCut++){
$result1 = getBestCut($hCut, $wide, $matrix);
$cutVal1 = $result1[0];
$cutList1 = $result1[1];
$result2 = getBestCut($high - $hCut, $wide, $matrix);
$cutVal2 = $result2[0];
$cutList2 = $result2[1];
$cutVal = $cutVal1 + $cutVal2;
if($cutVal > $bestVal){
$cutList = [$cutList1, $cutList2];
$bestVal = $cutVal;
$cutVert = CUT_VERT_FALSE;
$bestH = $hCut;
}
$checked[$hCut][$wide] = $result1;
$checked[$high - $hCut][$wide] = $result2;
}
for($vCut = 1; $vCut < 1 + floor($wide/2); $vCut++){
$result1 = getBestCut($hCut, $vCut, $matrix);
$cutVal1 = $result1[0];
$cutList1 = $result1[1];
$result2 = getBestCut($high, $wide - $vCut, $matrix);
$cutVal2 = $result2[0];
$cutList2 = $result2[1];
$cutVal = $cutVal1 + $cutVal2;
if($cutVal > $bestVal){
$cutList = [$cutList1, $cutList2];
$bestVal = $cutVal;
$cutVert = CUT_VERT_TRUE;
$bestH = $vCut;
}
$checked[$hCut][$vCut] = $result1;
$checked[$high][$wide - $vCut] = $result2;
}
if($cutVert == CUT_VERT_NONE){
$result = [$bestVal, [$high, $wide]];
}else if($cutVert == CUT_VERT_TRUE){
$result = [$bestVal - CUT_COST, $cutList];
}else{
$result = [$bestVal - CUT_COST, $cutList];
}
return $result;
}
Please tell me are they correct implementation of this method?
I wonder if time complexity is O(m^2*n^2) in top-down method?

Numerical sequence of 1 2 4

I need help in providing an algorithm for a numerical sequence which should display a series of 1 2 4 and its consecutive summations.
e.g. If my input value is 20, it should display
1 2 4 8 9 11 15 16 18
Wherein
1 = 1
2 = 1 + 1
4 = 2 + 2
8 = 4 + 4
And the summation of 1 and 2 and 4 will repeat again starting with the present number which is 8 and so on..
9 = 8 + 1
11 = 9 + 2
15 = 11 + 4
16 = 15 + 1
18 = 16 + 2
As you can see, it should not proceed to 22 (18 + 4) since our sample input value is 20. I hope you guys get my point. I'm having a problem in designing the algorithms in the for loop. What I have now which is not working is
$input = 20;
for ($i = $i; $i < $input; $i = $i+$i) {
if($i==0){
$i = 4;
$i = $i - 3;
}elseif($i % 4 == 0){
$i = $i + 1;
}
print_r("this is \$i = $i<br><br>");
}
NOTE: Only one variable and one for loop is required, it will not be accepted if we use functions or arrays. Please help me, this is one of the most difficult problems I've encountered in PHP..
you can use the code
$input = 20;
$current = 1;
$val = 1;
while($val < $input){
print_r("this is \$val = $val\n");
$val = $val + $current;
$current = ($current == 4 ? 1 : $current*2);
}
see the online compiler
Since you have mentioned Only one variable and one for loop is required
Try this,
$input = 20;
for ($i = 1; $i < $input; $i) {
if($i>$input) break;
print_r("this is \$i = $i<br><br>");
$i=$i+1;
if($i>$input) break;
print_r("this is \$i = $i<br><br>");
$i=$i+2;
if($i>$input) break;
print_r("this is \$i = $i<br><br>");
$i=$i+4;
}
Online Compiler
def getSeq(n):
if n == 1:
return [1]
temp = [1]
seq = [ 1, 2, 4]
count, current, prev = 0, 0, 1
while True:
current = prev + seq[count]
if current > n:
break
prev = current
temp += [current]
count = (count + 1) % 3
return temp
print getSeq(20)
I'm pretty sure that this one is going to work
the case that we have to take care of is n == 1 and return a static result [1].
in other cases the second value is repeating circularly and adding up to previous value.
This Python solution should be implementable in any reasonable language:
limit = 20
n = 1 << 2
while n >> 2 < limit:
print(n >> 2)
n = (((n >> 2) + (2 ** (n & 3))) << 2) + ((n & 3) + 1) % 3
Perl Equivalent (using the style of for loop you expect):
$limit = 20;
for ($n = 1 << 2; $n >> 2 < $limit; $n = ((($n >> 2) + (2 ** ($n & 3))) << 2) + (($n & 3) + 1) % 3) {
print($n >> 2, "\n");
}
OUTPUT
1
2
4
8
9
11
15
16
18
EXPLANATION
The basic solution is this:
limit = 20
n = 1
i = 0
while n < limit:
print(n)
n = n + (2 ** i)
i = (i + 1) % 3
But we need to eliminate the extra variable i. Since i only cycles through 0, 1 and 2 we can store it in two bits. So we shift n up two bits and store the value for i in the lower two bits of n, adjusting the code accordingly.
Not only one variable and one for loop, no if statements either!

How to parse a time in years in QBasic

How to parse a time (month/date/year) in Microsoft QBasic, needed for testing.
s = 'PT1H28M26S'
I would like to get:
num_mins = 88
You can parse such a time string with the code below, but the real question is:
Who still uses QBasic in 2015!?
CLS
s$ = "PT1H28M26S"
' find the key characters in string
posP = INSTR(s$, "PT")
posH = INSTR(s$, "H")
posM = INSTR(s$, "M")
posS = INSTR(s$, "S")
' if one of values is zero, multiplying all will be zero
IF ((posP * posH * posM * posS) = 0) THEN
' one or more key characters are missing
nummins = -1
numsecs = -1
ELSE
' get values as string
sHour$ = MID$(s$, posP + 2, (posH - posP - 2))
sMin$ = MID$(s$, posH + 1, (posM - posH - 1))
sSec$ = MID$(s$, posM + 1, (posS - posM - 1))
' string to integer, so we can calculate
iHour = VAL(sHour$)
iMin = VAL(sMin$)
iSec = VAL(sSec$)
' calculate totals
nummins = (iHour * 60) + iMin
numsecs = (iHour * 60 * 60) + (iMin * 60) + iSec
END IF
' display results
PRINT "Number of minutes: "; nummins
PRINT "Number of seconds: "; numsecs
PRINT "QBasic in 2015! w00t?!"
Simpler way to grab minutes from string in qbasic
REM Simpler way to grab minutes from string in qbasic
S$ = "PT1H28M26S"
S$ = MID$(S$, 3) ' 1H28M26S
V = INSTR(S$, "H") ' position
H = VAL(LEFT$(S$, V - 1)) ' hours
S$ = MID$(S$, V + 1) ' 28M26S
V = INSTR(S$, "M") ' position
M = VAL(LEFT$(S$, V - 1)) ' minutes
PRINT "num_mins ="; H * 60 + M

Looking for an algorithm that distributes a width to columns

I would like to print a database-table to STDOUT. If the table-width is greater than the screen-width I would like to cut the column each with the same percentage (unless a table-width has reached min_width) until the table fits in the screen. I've tried to solve this with the posted subroutine. Does somebody know a shorter and more elegant algorithm to solve this problem?
sub cal_size {
my ( $maxcols, $ref ) = #_;
# $maxcols => screen width
# $ref => ref to an AoA; holds the table
my ( $max ) = cal_tab( $ref );
# $max => ref to an array; holds the length of the longest string of each column
# $tab = 2;
if ( $max and #$max ) {
my $sum = sum( #$max ) + $tab * #$max;
$sum -= $tab;
my #max_tmp = #$max;
my $percent = 0;
while ( $sum > $maxcols ) {
$percent += 0.5;
if ( $percent > 99 ) {
return;
}
my $count = 0;
for my $i ( 0 .. $#max_tmp ) {
# $min_width => columns width should not be less than $min_width if possible
next if $min_width >= $max_tmp[$i];
# no need to cut if the column width id less than min_width
next if $min_width >= minus_x_percent( $max_tmp[$i], $percent );
# don't cut if column width become less than min_width
$max_tmp[$i] = minus_x_percent( $max_tmp[$i], $percent );
$count++;
last if $sum <= $maxcols;
}
$min_width-- if $count == 0 and $min_width > 1;
# if no cuts but $sum > $maxcols reduce $min_width
$sum = sum( #max_tmp ) + $tab * #max_tmp;
$sum -= $tab;
}
my $rest = $maxcols - $sum;
while ( $rest > 0 ) { # distribute the rest
my $count = 0;
for my $i ( 0 .. $#max_tmp ) {
if ( $max_tmp[$i] < $max->[$i] ) {
$max_tmp[$i]++;
$rest--;
$count++;
last if $rest < 1;
}
}
last if $count == 0;
last if $rest < 1;
}
$max = [ #max_tmp ] if #max_tmp;
}
return $max;
}
sub minus_x_percent {
my ( $value, $percent ) = #_;
return int $value - ( $value * 1/100 * $percent );
}
This problem would be simple if it wasn't for the lower limit for the field widths. Once a field cannot get any smaller only the larger ones are eligible for scaling, so the calculation varies depending on whether all, none, or some of the fields have been scaled down to their limit.
The scaling has several bands, one per unique field width. As the fields are scaled down in equal proportion the smallest of them will be the first to hit the minimum field size limit. After that only the columns bigger than the smallest size can be reduced any further until the second smallest also reaches the limit.
This continues until all columns have reached their minimum size, after which the available space is just divided equally between the columns.
This program implements the calculations for that algorithm, and I think does what you want.
Note that the returned field widths are floating-point values and you must round them as you see fit.
use strict;
use warnings;
use List::Util 'max';
my $min_col_width = 10;
my $tab = 2;
my $widths = recalc_widths(80, [ 10, 15, 20, 25, 30 ]);
print join ' ', map sprintf('%.3f', $_), #$widths;
print "\n";
sub recalc_widths {
my ($target, $widths) = #_;
$target -= (#$widths - 1) * $tab;
my #sorted_widths = sort { $a <=> $b } #$widths;
my $num_limited = 0;
my $adjustable_total_width = 0;
$adjustable_total_width += $_ for #sorted_widths;
while (#sorted_widths) {
my $boundary = $sorted_widths[0];
my $scale = ($target - $num_limited * $min_col_width) / $adjustable_total_width;
if ($boundary * $scale >= $min_col_width) {
return [ map max($_ * $scale, $min_col_width), #$widths ];
}
while (#sorted_widths and $sorted_widths[0] == $boundary) {
shift #sorted_widths;
$adjustable_total_width -= $boundary;
$num_limited++;
}
}
return [ ($target / $num_limited) x $num_limited ];
}
output
10.000 10.333 13.778 17.222 20.667
I think it's better to use a proper module from CPAN. If you can calc the width of each column, then configure each row print with Text::Format

Tune my code to solve a puzzle

5 monkey share n peaches, they cannot distribute equally. So the first monkey dump 1 peach, and total number of peaches can be divided by 5, and the first monkey took his part.
Then is the second monkey, -1 peach, can be divided by 5 and took his part.
Until the fifth monkey finished all the steps. There may be some peaches still left.
Give the minimum number of peaches that satisfy this condition.
perl code 1:
#!/usr/bin/perl -w
for $n (0..10000){ #this is basic idea but code is too messy !
if( ($n-1) % 5 == 0 ){
$remain = 4/5 * ($n -1 );
if( ($remain - 1) % 5 == 0){
$remain = 4/5 * ($remain -1 );
if( ($remain - 1) % 5 == 0){
$remain = 4/5 * ($remain -1 );
if( ($remain - 1) % 5 == 0){
$remain = 4/5 * ($remain -1 );
if( ($remain - 1) % 5 == 0){
$remain = 4/5 * ($remain -1 );
print "remain: $remain original: $n\n";
}
}
}
}
}
}
perl code 2:
sub doit($){
($n) = #_;
if( ($n - 1) % 5 ==0 ){ #if can be distributed by 5 monkey
$n = ($n - 1) * 4/5; #commit distribute
return $n;
}else{
return -1; #fail
}
}
for $n (0..10000){ #restriction
$r = $n; #"recursively" find solution
$o = $n; #backup n
$count = 0;
for ($i = 0; $i < 5; $i++){ #assume there is 5 monkey, it can be changed
$r = doit($r);
if($r == -1){ #skip once fail
last;
}
$count++;
}
if($count == 5){ # if pass 5 test, then you found the number !
print "now ".$r."\n";
print "origin ".$o."\n";
}
}
I am thinking to cut some code. But felt hard. Can anyone help ?
First of all, you really should use strict and warnings pragmas at the top of your scripts. Your $n usage is especially worrisome. In the future, if you declare variables with my but use the same name, you convey the fact that they will represent the same quantity, without the fear that they might collide.
Anyway here is a slightly polished, and more importantly strict and warnings safe version:
#!/usr/bin/env perl
use strict;
use warnings;
sub doit {
my ($n) = #_;
if( ($n - 1) % 5 ==0 ){ #if can be distributed by 5 monkey
$n = ($n - 1) * 4/5; #commit distribute
return $n;
} else {
return undef; #fail
}
}
OUTER: for my $n (0..10000){ #restriction
my $r = $n; #"recursively" find solution
for (1..5){ #assume there is 5 monkey, it can be changed
$r = doit($r);
next OUTER unless defined $r;
}
# if code gets here, then it passed 5 test, then you found the number !
print "now: $r\torigin: $n\n";
}
And now, if you really want to be fun with it (don't use this in production, readability first! ):
#!/usr/bin/env perl
use strict;
use warnings;
OUTER: for my $n (0..10000){
my $r = $n;
$r = ($r - 1) % 5 ? next OUTER : 4/5 * ($r - 1) for (1..5);
print "now: $r\torigin: $n\n";
}
or even golfed:
for(0..10000){$r=$n=$_;map$r*=--$r%5?next:4/5,1..5;print"now: $r\torigin: $n\n"}
Consider this solution:
sub share {
($_[0] - 1) % 5 == 0 ? ($_[0]-1)/5*4 : die "unable to share";
}
for my $i (1..10000) {
eval {
share(share(share(share(share($i)))));
};
unless ($#) {
print "solution: $i\n";
last;
}
}
I'm sure there is a monad lurking within.
I'm not 100% sure I understand your question, but instead of searching for the answer, start with the last monkey. The minimum peaches he could take is 1, and even though there could be some left, to get the minimum, assume there are 0 left. Now, calculate how many peaches the second to last monkey saw, and so on.
There is no need to loop, if you start from the last monkey
# set numPeaches to what the last monkey had
$numPeaches = 1;
# then, figure out how many the second to last monkey had, and add to numPeaches
# and, so on ...
# until you get to the first monkey

Resources