Get color value from numeric values - php

I need for a projet to get a color from a value.
I explain, I have datas and each data must be represented by a color.
The red color is for the maximum, and the blue for the minimum and the green is for the middle value. A kind of heatmap.
So, I need to have a function returning the right color.
I tried something like this :
function datatocolor($min, $max, $value)
{
$half = (($min + $max) / 2);
if ($value > $half)
{
$r = (255 * ($value+$min-$half)) / $half;
$g = 255 - $r;
$b = 0;
}
else {
$b = (255 * ($half-$value+$min)) / $half;
$g = 255 - $b;
$r = 0;
}
$color = array(intval($r), intval($g), intval($b));
return $color;
}
But, I get red and blue, and never green ... I tried a lot of operations, I must be stupid but I don't find the right operation ...
Thanks in advance for your help !

I'm not a php expert, but as far as I can tell, the problem isn't with this code block. I tested your algorithm in java just to be sure, and it looks to be correct:
public static void main(String[] args) {
int min = 0;
int max = 10;
int half = (min + max) / 2;
int r, g, b;
// Cycling through the values for completeness' sake.
for (int value = 0; value <= 10; value++) {
if (value > half) {
r = (255 * (value + min - half)) / half;
g = 255 - r;
b = 0;
} else {
b = (255 * (half - value + min)) / half;
g = 255 - b;
r = 0;
}
System.out.println("Value: " + value + " - " + new Color(r, g, b));
}
The output from this is what you would expect -- pure blue at minimum, pure green at the middle, and pure red at the maximum:
Value: 0 - java.awt.Color[r=0,g=0,b=255]
Value: 1 - java.awt.Color[r=0,g=51,b=204]
Value: 2 - java.awt.Color[r=0,g=102,b=153]
Value: 3 - java.awt.Color[r=0,g=153,b=102]
Value: 4 - java.awt.Color[r=0,g=204,b=51]
Value: 5 - java.awt.Color[r=0,g=255,b=0]
Value: 6 - java.awt.Color[r=51,g=204,b=0]
Value: 7 - java.awt.Color[r=102,g=153,b=0]
Value: 8 - java.awt.Color[r=153,g=102,b=0]
Value: 9 - java.awt.Color[r=204,g=51,b=0]
Value: 10 - java.awt.Color[r=255,g=0,b=0]
Based on what you've provided, the problem seems to be either in the way you're calling the function, or in the way you're using the array it returns.

Related

Iterations in VBA - Comparable method in PHP

Using VBA code I found in a spreadsheet to adapt to an online PHP application. The code uses the bisection method in mathematics to find optimal value for a calculation required to price options.
Upper = estimate_upper
Lower = estimate_lower
UUpper = container
Start_Iteration:
IterationCountE = 0.000000001
While (Upper - Lower) > IterationCountE
Mid = (Upper + Lower) / 2
c1 = calculations1...
c2 = calculations2...
If (c2 - c1) > 0 Then
Lower = Mid
Else
Upper = MId
End If
Wend 'Ends the while loop
If (Round(Mid, 4) = Round(UUpper, 4)) Then
Upper = 2 * UUpper
UUpper = Upper
GoTo Start_Iteration
End If
Function = Mid
For most part, I understand the mechanics of the iteration. My attempted PHP conversion is as follows:
$IterationCountE = 0.00000000001;
while ( ($Upper - $Lower) > $IterationCountE ) {
$Mid = ($Upper + $Lower) / 2;
$c1 = calculation1();
$c2 = calculation2();
if ( ($c2 - $c1) > 0 ) {
$Lower = $Mid;
} else {
$Upper = $Mid;
}
if (round($Mid, 4) == round($UUpper, 4)) {
$Upper = 2 * $UUpper;
$UUpper = $Upper;
}
}
return $Mid;
Is this the best way to approach an similar iteration in PHP? Would it be better to wrap the iteration in a function and refer back to it like in the VBA code?
I do not get the same value results when comparing the PHP output to the value from a macro.

Block scanning on sudoku solver explanation

I tried this sudoku solver http://www.emanueleferonato.com/2008/12/09/sudoku-creatorsolver-with-php/. It works fine.
Also see this spreadsheet to see more detail in calculation : spreadsheet
I understand how the row and col scanning. From the board, we know that:
index = 9*row + col
row = floor(index/9)
col = index % 9
And for the block, because it build from 3x3 board so the formula: block_index = 3*row_block + col_row. Because per block there are 3 rows and cols, so the formula for row_block = floor(row/3) and col_block = floor(col/3). From here we can conclude that:
block_index = 3*row_block + col_row
block_index = 3(floor(row/3)) + floor(col/3)
block_index = floor(row/3)*3 + floor(col/3)
This could explain for these function :
return_row
retun_col
return_block
is_possible_row
is_possible_col
But I cannot understand about is_possible_block function. Here is the function:
function is_possible_block($number,$block,$sudoku){
$possible = true;
for($x = 0;$x <= 8;$x++){
if($sudoku[floor($block / 3) * 27 + $x % 3 + 9 * floor($x / 3) + 3 * ($block % 3)] == $number){
$possible = false;
}
}
return $possible;
}
What I know about is_possible_block function is:
floor($block / 3) * 27 + $x % 3 + 9 * floor($x / 3) + 3 * ($block % 3)
= 9row+col
= 9(floor($block/3)*3 + floor($x/3)) + ($x%3 + 3*($block%3))
row = 3row_block+row_x_block
floor($block/3) = row_block
floor($x/3) = row_x_block
col = 3col_block+col_x_block
How col = 3col_block+col_x_block , because what I know, the formula should be like this : col = 3row_block+col.
I know col_x_block mean column position on 0-8 block. And row_block mean row position on 0-2 block.
How do you explain this formula? Thanks
UPDATE
Now I know. floor($block/3)*3 and 3*($block%3) determine top left corner in block. Then floor($x / 3) and $x % 3 moves each cell in the block.
I use it in c++
for(int k = ((x - 1) / 3) * 3 + 1; k < ((x - 1) / 3) * 3 + 4; k++
because of "x" is integer "/" operation return int value.
maybe 3(floor($block-1/3)) can help you.

Exponential function algorithm

I need to implement a function that interpolates an exponential curve from three points, but I'm not sure how to do it.
I have a graph that has the Y axis as percentage, 0 to 100% and X as 0 to 10.
The only points that I know are (50,7), (100,10) and (0,0).
I know I can create an array that has the percentages and values and loop through it, but this does not feel like the "right" way to do it. Is there a more direct algorithm?
I would use the formula :
partial : total = % : 100
partial (the value) = (total * %) / 100
Code
<?php
$points = array("8%,67%","36%,74%","73%,13%");
function return_value($percentage,$total) {
$value = ($total * $percentage) / 100.0;
return $value;
}
function evaluate_points($points) {
$max_x = 100.0; // As float value
$max_y = 10.0; // As float value
for ($point = 0; $point < count($points); $point++) {
//Replace the % sign
$points[$point] = str_replace("%", "", $points[$point]);
$point_percentages = explode(",", $points[$point]);
$x_percentage = $point_percentages[0];
$y_percentage = $point_percentages[1];
echo("The value for x is : ".return_value($x_percentage,$max_x) ."<br>");
echo("The value for y is : ".return_value($y_percentage,$max_y). "<br><br>");
}
}
evaluate_points($points);
?>
Output

LuhnCalc and bpay MOD10 version 5

I am using the following PHP code to calculate a CRN for BPay:
<?php
function LuhnCalc($number) {
$chars = array_reverse(str_split($number, 1));
$odd = array_intersect_key($chars, array_fill_keys(range(1, count($chars), 2), null));
$even = array_intersect_key($chars, array_fill_keys(range(0, count($chars), 2), null));
$even = array_map(function($n) { return ($n >= 5)?2 * $n - 9:2 * $n; }, $even);
$total = array_sum($odd) + array_sum($even);
return ((floor($total / 10) + 1) * 10 - $total) % 10;
}
print LuhnCalc($_GET['num']);
?>
However it seems that BPAY is version 5 of MOD 10, for which I can't find any documentation. It seems to not be the same as MOD10.
The following numbers where tested:
2005,1597,3651,0584,9675
bPAY
2005 = 20052
1597 = 15976
3651 = 36514
0584 = 05840
9675 = 96752
MY CODE
2005 = 20057
1597 = 15974
3651 = 36517
0584 = 05843
9675 = 96752
As you can see, none of them match the BPAY numbers.
This PHP function will generate BPay reference numbers based on the mod10 version 5 algorithm.
Who knows why BPay can't add this to their website. I only found an explanation by googling finding the algorithm being called "MOD10V05" instead of "Mod 10 version 5".
function generateBpayRef($number) {
$number = preg_replace("/\D/", "", $number);
// The seed number needs to be numeric
if(!is_numeric($number)) return false;
// Must be a positive number
if($number <= 0) return false;
// Get the length of the seed number
$length = strlen($number);
$total = 0;
// For each character in seed number, sum the character multiplied by its one based array position (instead of normal PHP zero based numbering)
for($i = 0; $i < $length; $i++) $total += $number{$i} * ($i + 1);
// The check digit is the result of the sum total from above mod 10
$checkdigit = fmod($total, 10);
// Return the original seed plus the check digit
return $number . $checkdigit;
}
Here's a way of implementing the "MOD10V5" algorithm (or "mod 10 version 5") using a t-sql user defined function in SQL server. It accepts a Customer ID up to 9 characters long, and return an 11 character CRN (Customer Reference Number).
I also prepended a version number onto the start of my CustomerID, you could do this too if you think you might end up changing it in the future.
CREATE Function [dbo].[CalculateBPayCRN]
(
#CustomerID nvarchar(9)
)
RETURNS varchar(11)
AS
BEGIN
DECLARE #NewCRN nvarchar(11)
DECLARE #Multiplier TINYINT
DECLARE #Sum int
DECLARE #SubTotal int
DECLARE #CheckDigit int
DECLARE #ReturnVal BIGINT
SELECT #Multiplier = 1
SELECT #SubTotal = 0
-- If it's less than 9 characters, pad it with 0's, then prepend a '1'
SELECT #NewCRN = '1' + right('000000000'+ rtrim(#CustomerID), 9)
-- loop through each digit in the #NewCRN, multiple it by the correct weighting and subtotal it:
WHILE #Multiplier <= LEN(#NewCRN)
BEGIN
SET #Sum = CAST(SUBSTRING(#NewCRN,#Multiplier,1) AS TINYINT) * #Multiplier
SET #SubTotal = #SubTotal + #Sum
SET #Multiplier = #Multiplier + 1
END
-- mod 10 the subtotal and the result is our check digit
SET #CheckDigit = #SubTotal % 10
SELECT #ReturnVal = #NewCRN + cast(#CheckDigit as varchar)
RETURN #ReturnVal
END
GO
Modula 10 V1 in PHP. Tested against my Windows dataflex routine and it is the same.
function generateBpayRef($number) {
//Mod 10 v1
$number = preg_replace("/\D/", "", $number);
// The seed number needs to be numeric
if(!is_numeric($number)) return false;
// Must be a positive number
if($number <= 0) return false;
$stringMemberNo = "$number";
$stringMemberNo = str_pad($stringMemberNo, 6, "0", STR_PAD_LEFT);
//echo " Padded Number is $stringMemberNo ";
$crn = $stringMemberNo;
for($i=0;$i<7;$i++){
$crnval = substr($crn,(5-$i),1);
$iPartVal = $iWeight * $crnval;
if($iPartVal>9){
//echo " Greater than 9: $iPartVal ";
$firstChar = substr($iPartVal,0,1);
$secondChar = substr($iPartVal,1,1);
$iPartVal=$firstChar+$secondChar;
//$iPartVal -= 9;
}
$iSum+=$iPartVal;
$iWeight++;
if ($iWeight>2){$iWeight=1;}
//echo " CRN: $crnval ] Weight: $iWeight ] Part: $iPartVal ] SUM: $iSum ";
}
$iSum %= 10;
if($iSum==0){
//echo " zero check is $iSum ";
//return $iSum;
}
else{
//return 10-$iSum;
$iSum=(10-$iSum);
}
//echo " Check is a $iSum ";
$BpayMemberNo = $stringMemberNo . $iSum ;
echo " New: $BpayMemberNo ";
return ($BpayMemberNo);
}
Here is a ruby class I whipped up quickly for Mod 10 v5
module Bpay
class CRN
attr_accessor :number, :crn
class << self
def calculate_for(number)
new(number).crn
end
end
def initialize(number)
#number = number
calculate
end
def calculate
raise ArgumentError, "The number '#{number}' is not valid" unless valid?
digits = number.to_s.scan(/\d/).map { |x| x.to_i }
raise ArgumentError, "The number '#{number}' must be at least 2 digits in length" if digits.size < 2
check_digit = digits.each_with_index.map { |d, i| d * (i + 1) }.inject(:+) % 10
#crn = "#{number}#{check_digit}"
end
def valid?
return false unless !!Integer(number.to_s) rescue false
return false if number.to_i <= 0
true
end
end
end
This is in C#, but this is what I have so far for BPay check digit generation:
private void btnBPayGenerate_Click(object sender, EventArgs e)
{
var originalChars = txtBPayNumber.Text.ToCharArray();
List<int> oddDigits = new List<int>();
List<int> evenDigits = new List<int>();
int oddTotal = 0, evenTotal = 0, total = 0, checkDigit ;
const int oddMultiplier = 3;
const int modulus = 10;
bool isOdd = true;
for (int x = 0; x < originalChars.Length; x++)
{
if(isOdd)
oddDigits.Add(Int32.Parse(originalChars[x].ToString()));
else
evenDigits.Add(Int32.Parse(originalChars[x].ToString()));
isOdd = !isOdd;
}
foreach (var digit in oddDigits)
oddTotal += digit;
foreach (var digit in evenDigits)
evenTotal += digit;
oddTotal = oddTotal * oddMultiplier;
total = oddTotal + evenTotal;
checkDigit = (modulus - (total % modulus));
lblBPayResult.Text = txtBPayNumber.Text + checkDigit.ToString();
}
I haven't completed testing this yet, I will post back once BPAY get back to me.
EDIT: try this: https://gist.github.com/1287893
I had to work out a version for javascript, this is what I came up with. It correctly generates the expected numbers in the original question.
var startingNumber = 2005;
var reference = startingNumber.toString();
var subTotal = 0;
for (var x = 0; x < reference.length; x++) {
subTotal += (x + 1) * reference.charAt(x);
}
var digit = subTotal % 10;
var bpayReference = reference + digit.toString();
Here is a function I created using vb.net to calculate a mod 10 version 5 check digit
Private Function CalcCheckDigit(ByRef psBaseNumber As String) As String
Dim lCheckDigit, iLoop As Integer
Dim dCalcNumber As Double
lCheckDigit = 0
dCalcNumber = 0
For iLoop = 0 To (psBaseNumber.Length - 1)
lCheckDigit = lCheckDigit + (psBaseNumber.Substring(iLoop, 1) * (iLoop + 1))
Next iLoop
lCheckDigit = lCheckDigit Mod 10
CalcCheckDigit = psBaseNumber & CStr(lCheckDigit)
End Function

How to write a function to determine the population count of a 16-bit integer using php or javascript?

How to write a function to determine the population count of a 16-bit
integer using php or javascript. Population count is defined as the number of bits that are
"turned on," or in others, it is the number of 1s in a binary
representation of a number. For example, the binary number 0b0000 has
a population count of 0 because there aren't any 1 bits. 0b0101 has a
population count of 2, because 2 bits turned on; 0b1110 has a
population count of 3. 0b1111111111111111 has a population count if 16
because there are sixteen 1 bits. Your function should accept an INTEGER
argument and return an INTEGER containing its population count. Example:
f(0) = 0
f(1) = 1
f(2) = 1
f(3) = 2
f(4) = 1
f(5) = 2
Using bitwise and and right shift
function count(n){
c =0;
while(n){
c += n&1;
n = n>>1;
}
return c;
}
The badass way?
var x=0xfffe;
x -= ((x >> 1) & 0x55555555);
x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
x = (((x >> 4) + x) & 0x0f0f0f0f);
x += (x >> 8);
x += (x >> 16);
alert(x & 0x0000003f); //15
Not necessarily badass, but it works...
<?php
$number = 3;
echo "Number: " . $number . "\n";
$bin_number = decbin($number);
$population_count = 0;
echo "Binary String Conversion: " . $bin_number . "\n";
for ($i = strlen($bin_number) - 1; $i >= 0; --$i) {
$population_count += $bin_number[$i];
}
echo "Population Count: " . $population_count . "\n";
?>

Categories