I want to add code 128 auto barcode in codeigniter framework.I used http://davidscotttufts.com/2009/03/31/how-to-create-barcodes-in-php/ for this but it is generating code128B format.I have also used http://www.barcodephp.com/en/download but could not be able to properly add classes in codeigniter framework.Can anyone help me or suggest me code128 auto barcode php script.
Thanks in advance
<?php
// Get thickness parameter from $_GET:
$thickness = ( isset( $_GET["thickness"] ) ? $_GET[ "thickness" ] : 2 );
$text = (isset($_GET["text"])?$_GET["text"]:"00000000024");
//$text=(int)$text;
$size = (isset($_GET["size"])?$_GET["size"]:"30");
$orientation = (isset($_GET["orientation"])?$_GET["orientation"]:"horizontal");
$code_type = (isset($_GET["codetype"])?$_GET["codetype"]:"code128");
$code_string = "";
// Translate the $text into barcode the correct $code_type
if ( strtolower($code_type) == "code128" ) {
$code_array = array(
0 => '11011001100',
1 => '11001101100',
2 => '11001100110',
3 => '10010011000',
4 => '10010001100',
5 => '10001001100',
6 => '10011001000',
7 => '10011000100',
8 => '10001100100',
9 => '11001001000',
10 => '11001000100',
11 => '11000100100',
12 => '10110011100',
13 => '10011011100',
14 => '10011001110',
15 => '10111001100',
16 => '10011101100',
17 => '10011100110',
18 => '11001110010',
19 => '11001011100',
20 => '11001001110',
21 => '11011100100',
22 => '11001110100',
23 => '11101101110',
24 => '11101001100',
25 => '11100101100',
26 => '11100100110',
27 => '11101100100',
28 => '11100110100',
29 => '11100110010',
30 => '11011011000',
31 => '11011000110',
32 => '11000110110',
33 => '10100011000',
34 => '10001011000',
35 => '10001000110',
36 => '10110001000',
37 => '10001101000',
38 => '10001100010',
39 => '11010001000',
40 => '11000101000',
41 => '11000100010',
42 => '10110111000',
43 => '10110001110',
44 => '10001101110',
45 => '10111011000',
46 => '10111000110',
47 => '10001110110',
48 => '11101110110',
49 => '11010001110',
50 => '11000101110',
51 => '11011101000',
52 => '11011100010',
53 => '11011101110',
54 => '11101011000',
55 => '11101000110',
56 => '11100010110',
57 => '11101101000',
58 => '11101100010',
59 => '11100011010',
60 => '11101111010',
61 => '11001000010',
62 => '11110001010',
63 => '10100110000',
64 => '10100001100',
65 => '10010110000',
66 => '10010000110',
67 => '10000101100',
68 => '10000100110',
69 => '10110010000',
70 => '10110000100',
71 => '10011010000',
72 => '10011000010',
73 => '10000110100',
74 => '10000110010',
75 => '11000010010',
76 => '11001010000',
77 => '11110111010',
78 => '11000010100',
79 => '10001111010',
80 => '10100111100',
81 => '10010111100',
82 => '10010011110',
83 => '10111100100',
84 => '10011110100',
85 => '10011110010',
86 => '11110100100',
87 => '11110010100',
88 => '11110010010',
89 => '11011011110',
90 => '11011110110',
91 => '11110110110',
92 => '10101111000',
93 => '10100011110',
94 => '10001011110',
95 => '10111101000',
96 => '10111100010',
97 => '11110101000',
98 => '11110100010',
99 => '10111011110',
100 => '10111101110',
101 => '11101011110',
102 => '11110101110',
'c' => '10111011110',
'b' => '10111101110',
'a' => '11101011110',
'A' => '11010000100',
'B' => '11010010000',
'C' => '11010011100',
'S' => '1100011101011'
);
$code = array();
$strCode;
// settype($code,'string');
//$this->sourceCode = $code;
$nbKr = strlen($code);
$strCode = '';
for( $i=0; $i<$nbKr; $i++ ) {
$code[$i] = substr($code, $i, 1);
}
$strCode = $code_array['B']; // Start
$checksum = 104 ;
$j = 1 ;
for( $i=0; $i<$nbKr; $i++ ) {
$tmp = ord($code[$i]) - 32 ;
$checksum += ( $j++ * $tmp ) ;
$strCode .= $code_array[$tmp];
}
$checksum %= 103 ;
$strCode .= $code_array[$checksum];
$strCode .= $code_array['S']; // Stop
$strCode = $strCode;
$tmp = strlen($strCode) + 20;
$width = $tmp;
}
// Pad the edges of the barcode
$code_length = 20;
for ( $i=1; $i <= strlen($code_string); $i++ )
$code_length = $code_length + (integer)(substr($code_string,($i-1),1));
if ( strtolower($orientation) == "horizontal" ) {
//$img_width = $code_length;
$img_width = $code_length * $thickness;
$img_height = $size;
} else {
$img_width = $size;
$img_height = $code_length;
}
$image = imagecreate($img_width, $img_height);
$black = imagecolorallocate ($image, 0, 0, 0);
$white = imagecolorallocate ($image, 255, 255, 255);
imagefill( $image, 0, 0, $white );
//$location = 10;
$location = 10 * $thickness;
for ( $position = 1 ; $position <= strlen($code_string); $position++ ) {
//$cur_size = $location + ( substr($code_string, ($position-1), 1);
$cur_size = $location + ( substr($code_string, ($position-1), 1) *$thickness);
if ( strtolower($orientation) == "horizontal" )
imagefilledrectangle( $image, $location, 0, $cur_size, $img_height, ($position % 2 == 0 ? $white : $black) );
else
imagefilledrectangle( $image, 0, $location, $img_width, $cur_size, ($position % 2 == 0 ? $white : $black) );
$location = $cur_size;
}
// Draw barcode to the screen
header ('Content-type: image/png');
imagepng($image);
imagedestroy($image);
?>
You can actually follow the examples at https://github.com/tecnickcom/tc-lib-barcode/blob/develop/example/index.php
For example:
$bobj = $barcode->getBarcodeObj('QRCODE,H', 'hello world', -4, -4, 'black');
echo "<img alt=\"Embedded Image\" src=\"data:image/png;base64,".base64_encode($bobj->getPngData())."\" />";
or if you want to print the barcode in a different format:
echo $bobj->getHtmlDiv();
The examples uses the tc-lib-barcode (https://github.com/tecnickcom/tc-lib-barcode) PHP Software library to generate both linear and bidimensional barcodes.
The source code is fully PSR-2 compliant and can be easily added to your PHP projects using Composer.
The original code has been ported and refactored from TCPDF and already used in billions of documents.
Related
I have to display result as
दुई खर्ब सतासी अर्ब अन्ठान्नब्बे करोड नब्बे लाख बाह्र हजार तीन सय पचहत्तर ...
It displays result correctly till five numbers..
But it doesn't display as needed when we use six numbers....
like 111111 .... It displays "एक सय एघार हजार एक सय एघार"
Where as it must be as "एक लाख एघार हजार एक सय एघार" .....
In case of seven and more numbers it throws error....
error 'Undefined offset: 1000000 in.....' ...
<?php
function convert_number_to_words($number) {
$hyphen = '-';
$conjunction = ' ';
$separator = ' ';
$negative = 'negative ';
$decimal = ' point ';
$dictionary = array(
0 => 'शुन्य',
1 => 'एक',
2 => 'दुई',
3 => 'तीन',
4 => 'चार',
5 => 'पाँच',
6 => 'छ',
7 => 'सात',
8 => 'आठ',
9 => 'नौ',
10 => 'दश',
11 => 'एघार',
12 => 'बाह्र',
13 => 'तेह्र',
14 => 'चौध',
15 => 'पन्ध',
16 => 'सोह्र',
17 => 'सत्र',
18 => 'अठार',
19 => 'उन्नाइस',
20 => 'विस',
21 => 'एक्काइस',
22 => 'बाइस',
23 => 'तेइस',
24 => 'चौविस',
25 => 'पच्चिस',
26 => 'छब्बिस',
27 => 'सत्ताइस',
28 => 'अठ्ठाईस',
29 => 'उनन्तिस',
30 => 'तिस',
31 => 'एकत्तिस',
32 => 'बत्तिस',
33 => 'तेत्तिस',
34 => 'चौँतिस ',
35 => 'पैँतिस',
36 => 'छत्तिस',
37 => 'सैँतीस',
38 => 'अठतीस',
39 => 'उनन्चालीस',
40 => 'चालीस',
41 => 'एकचालीस',
42 => 'बयालीस',
43 => 'त्रियालीस',
44 => 'चवालीस',
45 => 'पैँतालीस',
46 => 'छयालीस',
47 => 'सरचालीस',
48 => 'अठचालीस',
49 => 'उनन्चास',
50 => 'पचास',
51 => 'एकाउन्न',
52 => 'बाउन्न',
53 => 'त्रिपन्न',
54 => 'चउन्न',
55 => 'पचपन्न',
56 => 'छपन्न',
57 => 'सन्ताउन्न ',
58 => 'अन्ठाउन्न',
59 => 'उनन्साठी',
60 => 'साठी',
61 => 'एकसट्ठी',
62 => 'बयसट्ठी',
63 => 'त्रिसट्ठी',
64 => 'चौंसट्ठी',
65 => 'पैंसट्ठी',
66 => 'छयसट्ठी',
67 => 'सतसट्ठी',
68 => 'अठसट्ठी',
69 => 'उनन्सत्तरी',
70 => 'सत्तरी',
71 => 'एकहत्तर',
72 => 'बहत्तर',
73 => 'त्रिहत्तर',
74 => 'चौहत्तर',
75 => 'पचहत्तर',
76 => 'छयहत्तर',
77 => 'सतहत्तर',
78 => 'अठहत्तर',
79 => 'उनासी',
80 => 'असी',
81 => 'एकासी',
82 => 'बयासी',
83 => 'त्रियासी',
84 => 'चौरासी',
85 => 'पचासी',
86 => 'छयासी',
87 => 'सतासी',
88 => 'अठासी',
89 => 'उनान्नब्बे',
90 => 'नब्बे',
91 => 'एकान्नब्बे',
92 => 'बयानब्बे',
93 => 'त्रियान्नब्बे',
94 => 'चौरान्नब्बे',
95 => 'पन्चानब्बे',
96 => 'छयान्नब्बे',
97 => 'सन्तान्नब्बे',
98 => 'अन्ठान्नब्बे',
99 => 'उनान्सय',
100 => 'सय',
1000 => 'हजार',
100000 => 'लाख',
10000000 => 'करोड',
1000000000 => 'अर्ब',
100000000000 => 'खर्ब'
);
if (!is_numeric($number)) {
return false;
}
if (($number >= 0 && (int) $number < 0) || (int) $number < 0 -
PHP_INT_MAX) {
trigger_error(
'convert_number_to_words only accepts numbers between -' .
PHP_INT_MAX . ' and ' . PHP_INT_MAX,
E_USER_WARNING
);
return false;
}
if ($number < 0) {
return $negative . convert_number_to_words(abs($number));
}
$string = $fraction = null;
if (strpos($number, '.') !== false) {
list($number, $fraction) = explode('.', $number);
}
switch (true) {
case $number < 100:
$string = $dictionary[$number];
break;
case $number < 100:
$tens = ((int) ($number / 10)) * 10;
$units = $number % 10;
$string = $dictionary[$tens];
if ($units) {
$string .= $hyphen . $dictionary[$units];
}
break;
case $number < 1000:
$hundreds = $number / 100;
$remainder = $number % 100;
$string = $dictionary[$hundreds] . ' ' . $dictionary[100];
if ($remainder) {
$string .= $conjunction . convert_number_to_words($remainder);
}
break;;
default:
$baseUnit = pow(100000, floor(log($number, 100000)));
$numBaseUnits = (int) ($number / $baseUnit);
$remainder = $number % $baseUnit;
$string = convert_number_to_words($numBaseUnits) . ' ' .
$dictionary[$baseUnit];
if ($remainder) {
$string .= $remainder < 100 ? $conjunction : $separator;
$string .= convert_number_to_words($remainder);
}
break;
}
if (null !== $fraction && is_numeric($fraction)) {
$string .= $decimal;
$words = array();
foreach (str_split((string) $fraction) as $number) {
$words[] = $dictionary[$number];
}
$string .= implode(' ', $words);
}
return $string;
}
?>
Page "numtoword.php"
Page "index.php"
<?php
include('numword.php');
echo convert_number_to_words(287989012375);
?>
It looks like you are making it more difficult than it needs to be. I created a simpler recursive function, moved the dictionary and settings outside the function (generating a dictionary array on every function call was eating up a LOT of memory and is not necessary). I didn't include fractions but this should be a good starting point to expand off of:
<?php
$devnagriNumeralWords = [
'dictionary' => [
'smallUnits' => [
0 => 'शुन्य',
1 => 'एक',
2 => 'दुई',
3 => 'तीन',
4 => 'चार',
5 => 'पाँच',
6 => 'छ',
7 => 'सात',
8 => 'आठ',
9 => 'नौ',
10 => 'दश',
11 => 'एघार',
12 => 'बाह्र',
13 => 'तेह्र',
14 => 'चौध',
15 => 'पन्ध',
16 => 'सोह्र',
17 => 'सत्र',
18 => 'अठार',
19 => 'उन्नाइस',
20 => 'विस',
21 => 'एक्काइस',
22 => 'बाइस',
23 => 'तेइस',
24 => 'चौविस',
25 => 'पच्चिस',
26 => 'छब्बिस',
27 => 'सत्ताइस',
28 => 'अठ्ठाईस',
29 => 'उनन्तिस',
30 => 'तिस',
31 => 'एकत्तिस',
32 => 'बत्तिस',
33 => 'तेत्तिस',
34 => 'चौँतिस ',
35 => 'पैँतिस',
36 => 'छत्तिस',
37 => 'सैँतीस',
38 => 'अठतीस',
39 => 'उनन्चालीस',
40 => 'चालीस',
41 => 'एकचालीस',
42 => 'बयालीस',
43 => 'त्रियालीस',
44 => 'चवालीस',
45 => 'पैँतालीस',
46 => 'छयालीस',
47 => 'सरचालीस',
48 => 'अठचालीस',
49 => 'उनन्चास',
50 => 'पचास',
51 => 'एकाउन्न',
52 => 'बाउन्न',
53 => 'त्रिपन्न',
54 => 'चउन्न',
55 => 'पचपन्न',
56 => 'छपन्न',
57 => 'सन्ताउन्न ',
58 => 'अन्ठाउन्न',
59 => 'उनन्साठी',
60 => 'साठी',
61 => 'एकसट्ठी',
62 => 'बयसट्ठी',
63 => 'त्रिसट्ठी',
64 => 'चौंसट्ठी',
65 => 'पैंसट्ठी',
66 => 'छयसट्ठी',
67 => 'सतसट्ठी',
68 => 'अठसट्ठी',
69 => 'उनन्सत्तरी',
70 => 'सत्तरी',
71 => 'एकहत्तर',
72 => 'बहत्तर',
73 => 'त्रिहत्तर',
74 => 'चौहत्तर',
75 => 'पचहत्तर',
76 => 'छयहत्तर',
77 => 'सतहत्तर',
78 => 'अठहत्तर',
79 => 'उनासी',
80 => 'असी',
81 => 'एकासी',
82 => 'बयासी',
83 => 'त्रियासी',
84 => 'चौरासी',
85 => 'पचासी',
86 => 'छयासी',
87 => 'सतासी',
88 => 'अठासी',
89 => 'उनान्नब्बे',
90 => 'नब्बे',
91 => 'एकान्नब्बे',
92 => 'बयानब्बे',
93 => 'त्रियान्नब्बे',
94 => 'चौरान्नब्बे',
95 => 'पन्चानब्बे',
96 => 'छयान्नब्बे',
97 => 'सन्तान्नब्बे',
98 => 'अन्ठान्नब्बे',
99 => 'उनान्सय'
],
'largeUnits' => [
100 => 'सय',
1000 => 'हजार',
100000 => 'लाख',
10000000 => 'करोड',
1000000000 => 'अर्ब',
100000000000 => 'खर्ब'
]
],
'hyphen' => '-',
'conjunction' => ' ',
'separator' => ' ',
'negative' => 'negative ',
'decimal' => ' point '
];
function convert_devnagri_number_to_words($number) {
global $devnagriNumeralWords;
$numLen = strlen($number);
$output = [ 'prefix' => '', 'base' => '', 'suffix' => '' ];
$base = pow(10, $numLen-1);
$smallestLargeUnit = array_keys($devnagriNumeralWords['dictionary']['largeUnits'])[0];
$isNegative = $number < 0;
if( $isNegative ) {
$output['prefix'] .= $devnagriNumeralWords['negative'];
$number = abs($number);
}
if( $number < $smallestLargeUnit ) {
// Number is less than 100
$prefix = $number;
} else {
// Get base amount (100, 1000, 100000, etc)
if( isset($devnagriNumeralWords['dictionary']['largeUnits'][$base]) ) {
$largeUnit = $devnagriNumeralWords['dictionary']['largeUnits'][$base];
} else {
// No exact large unit match, find next smallest
while( $base >= $smallestLargeUnit ) {
$base = (int) ($base / 10);
if( isset($devnagriNumeralWords['dictionary']['largeUnits'][$base]) ) {
break; // Found a match!
}
}
}
$output['base'] .= $devnagriNumeralWords['dictionary']['largeUnits'][$base];
// Get prefix, e.g. "28" when number is 28564
$prefix = (int) ($number / $base);
// Subtract prefix to get next part to process
// E.g. the next number is 345 when the number is 85345
$nextNumber = $number - ($prefix * $base);
if( $nextNumber > 0 )
$output['suffix'] = convert_devnagri_number_to_words($nextNumber);
}
if( $prefix >= 0 ) {
$output['prefix'] .= $devnagriNumeralWords['dictionary']['smallUnits'][$prefix];
}
// Put it all together!
return implode( $devnagriNumeralWords['separator'], array_filter($output) );
}
echo convert_devnagri_number_to_words(287989012375);
I want to calculate the totals for a series of columns in a table, how do I go about doing this?
Here is a sample of the data I want to sum:
array:1 [
"traders" => array:6 [
"Jim Mayor__targeted_target" => array:2 [
"amounts" => array:13 [
0 => 5
1 => 5
2 => 0
3 => 0
4 => 0
5 => 0
6 => 0
7 => 0
8 => 0
9 => 0
10 => 0
11 => 0
]
"row_name" => "Targeted target"
]
"Jim Mayor__actual_targeted" => array:2 [
"amounts" => array:13 [
0 => 0
1 => 1
2 => 0
3 => 0
4 => 0
5 => 0
6 => 1
7 => 1
8 => 0
9 => 0
10 => 0
11 => 0
]
"row_name" => "Actual targeted"
]
"Bob Martinez__targeted_target" => array:2 [
"amounts" => array:13 [
0 => 1
1 => 0
2 => 0
3 => 0
4 => 0
5 => 0
6 => 0
7 => 0
8 => 0
9 => 0
10 => 0
11 => 0
]
"row_name" => "Targeted target"
]
"Bob Martinez__actual_targeted" => array:2 [
"amounts" => array:13 [
0 => 19
1 => 45
2 => 20
3 => 26
4 => 21
5 => 10
6 => 12
7 => 20
8 => 11
9 => 2
10 => 0
11 => 0
]
"row_name" => "Actual targeted"
]
...
I want to sum together each index, e.g. for Jim Mayor__targeted_target, index 0 added to index 0 of Bob Martinez__targeted_target (this gives the total for January). It needs to work with an unlimited number of traders.
The function that generates the data:
protected function addRow($func, $params, $data, $year, $traderName, $rowName, $type, $image = null, $format = null, $underline = false)
{
$date = Carbon::createFromDate($year, 4, 1);
$total = 0;
$traderName = $traderName . '__' . str_replace(' ', '_', strtolower($rowName));
for ($i = 1; $i < 13; $i++) {
$params[1] = $date->year;
$params[2] = $date->month;
$result = call_user_func_array($func, $params);
$data['traders'][$traderName]['amounts'][] = $result ? $result : 0;
$total += $result;
$date->addMonth();
}
$data['traders'][$traderName]['amounts'][] = $total;
$data['traders'][$traderName]['row_name'] = $rowName;
return $data;
}
Just go over your data and save results in an additional array:
$results = array();
foreach ($traders as $trader) {
foreach ($trader['amounts'] as $i => $amount) {
if (!isset($results[$i])) {
$results[$i] = 0;
}
$results[$i] += $amount;
}
}
The result array will contains the sums of all traders.
Not tested but should work.
Do something like this:
function sumRowsByMonth($traders)
{
$sums = array_fill(0, 12, 0);
foreach($traders as $trader) {
foreach($trader['amounts'] as $monthId => $amount) {
$sums[$monthId] += $amount;
}
}
return $sums;
}
I tested with this:
$arr = array(
'traders' => array(
'Jim Mayor__targeted_target' => array(
'amounts' => array(
0 => 5,
1 => 5,
2 => 0,
3 => 0,
4 => 0,
5 => 0,
6 => 0,
7 => 0,
8 => 0,
9 => 0,
10 => 0,
11 => 0,
)
),
'Bob Martinez__targeted_target' => array(
'amounts' => array(
0 => 19,
1 => 45,
2 => 20,
3 => 26,
4 => 21,
5 => 10,
6 => 12,
7 => 20,
8 => 11,
9 => 2,
10 => 0,
11 => 0,
)
),
),
);
var_dump(sumRowsByMonth($arr['traders']));
Use array_sum() function.
array_sum() returns the sum of values in an array
Also, you said you want to count targeted target and actual targeted separately.
$actual = [];
$targeted = [];
foreach ($traders as $trader) {
$sum = array_sum($trader['anmounts']);
$trader['row_name'] === 'Actual targeted') ? $actual += $sum : $target += $sum;
}
Maybe you'll need to modify this a little bit to tune behavior, but I guess I got the idea.
#imperium2335:
The main problem I keep getting that it is summing all rows, including actual_targeted. actual_targeted needs to be grouped and summed separately to targeted_target.
Then do this:
function sumRowsByMonth($traders)
{
$sums = array();
foreach($traders as $traderName => $trader) {
$type = strstr($traderName, '__');
if( empty($sums[$type]) ) {
$sums[$type] = array_fill(0, 12, 0);
}
foreach($trader['amounts'] as $monthId => $amount) {
$sums[$type][$monthId] += $amount;
}
}
return $sums;
}
Read this:
http://php.net/manual/en/function.strstr.php
I have an array like this:
$array = array(10,25,47,14,45,58,25,29,15,36,45,15,25,27,34);
is there a way to output a new array of 10 ranges with key that tells me which is used and frequency as values?
$result = array(
[x0] => frequency // number of values <= x0
[x1] => frequency // number of values > x0 and <=1
etc..., [x2], ...., [x7], x[8]
[x9] => frequency // number of values >= x9
)
use this for 10 equal segments
$array = array(10,25,47,14,45,58,25,29,15,36,45,15,25,27,34);
$step = (max($array) - min($array)) / 10;
$result = [];
for ($i = min($array); $i < max($array) - $step; $i += $step) {
$res = array_filter($array, function($v) use ($i, $step) {
return ($i <= $v) && $v < $i +$step;
});
$result[$i . '-' . ($i + $step)] = $res;
}
Return:
"10 - 14.8" => 2
"14.8 - 19.6" => 2
"19.6 - 24.4" => 0
"24.4 - 29.2" => 5
"29.2 - 34" => 0
"34 - 38.8" => 2
"38.8 - 43.6" => 0
"43.6 - 48.4" => 3
"48.4 - 53.2" => 0
"53.2 - 58" => 0
You can use array_count_values() to count values
$array = array(10,25,47,14,45,58,25,29,15,36,45,15,25,27,34);
$vals = array_count_values($array);
echo "<pre>"; print_r($vals);
This will give you
Array
(
[10] => 1
[25] => 3
[47] => 1
[14] => 1
[45] => 2
[58] => 1
[29] => 1
[15] => 2
[36] => 1
[27] => 1
[34] => 1
)
I've used an array for the range boundaries. Here with an example of 4 irregular ranges. And dumped the sorted array to make it easier to see if the results are as you'd expect.
<?php
$array = array(10,25,47,14,45,58,25,29,15,36,45,15,25,27,34);
$bounds = array(0,10,25,50,100);
$lower = array_shift($bounds);
$range_frequencies = array();
sort($array);
var_dump($array);
foreach($bounds as $upper) {
$range_frequencies[$lower . '-' . $upper] = 0;
foreach($array as $k => $v) {
if($v > $lower && $v <= $upper) {
$range_frequencies[$lower . '-' . $upper]++;
unset($array[$k]);
}
}
$lower = $upper;
}
var_dump($range_frequencies);
Output:
array (size=15)
0 => int 10
1 => int 14
2 => int 15
3 => int 15
4 => int 25
5 => int 25
6 => int 25
7 => int 27
8 => int 29
9 => int 34
10 => int 36
11 => int 45
12 => int 45
13 => int 47
14 => int 58
array (size=4)
'0-10' => int 1
'10-25' => int 6
'25-50' => int 7
'50-100' => int 1
Based on Manjeet Barnala's answer:
$array = array(10,25,47,14,45,58,25,29,15,36,45,15,25,27,34);
$vals = array_count_values($array);
arsort($vals);
$vals = array_slice($vals,0,10,true);
var_dump($vals);
I wrote a FFT (Fast Fourier Transform) module for PHP recently. When I tried to test it, It always throws an error that the array $this->reverseTable has some index not defined. I got no clue of how to solve this problem.
Here's the PHP code:
<?php
class FourierTransform {
public $bufferSize;
public $sampleRate;
public $bandwidth;
public $spectrum = array();
public $real = array();
public $imag = array();
public $peakBand = 0;
public $peak = 0;
public function __construct($bufferSize,$sampleRate){
$this->bufferSize = $bufferSize;
$this->sampleRate = $sampleRate;
$this->bandwidth = 2 / $bufferSize * $sampleRate / 2;
}
public function getBandFrequency($index){
return $this->bandwidth * $index + $this->bandwidth / 2;
}
public function calculateSpectrum(){
$bSi = 2 / $this->bufferSize;
for($i = 0,$N = $this->bufferSize/2; $i < $N; $i++){
$rval = $this->real[$i];
$ival = $this->imag[$i];
$mag = $bSi * sqrt($rval * $rval + $ival * $ival);
if($mag > $this->peak){
$this->peakBand = $i;
$this->peak = $mag;
}
$this->spectrum[$i] = $mag;
}
}
}
class FFT extends FourierTransform {
public $reverseTable = array();
public $sinTable = array();
public $cosTable = array();
public function __construct($bufferSize,$sampleRate){
parent::__construct($bufferSize,$sampleRate);
$limit = 1;
$bit = $bufferSize >> 1;
while($limit < $bufferSize){
for($i = 0; $i < $limit; $i++){
$this->reverseTable[$i + $limit] = $this->reverseTable[$i] + $bit;
}
$limit = $limit << 1;
$bit = $bit >> 1;
}
for($i = 0; $i < $bufferSize; $i++){
$this->sinTable[$i] = sin(-M_PI / $i);
$this->cosTable[$i] = cos(-M_PI / $i);
}
}
public function foward($buffer){
$k = floor(log($this->bufferSize,2));
if(pow(2,$k) !== $this->bufferSize) throw new Exception('Invalid buffer size, must be a power of 2.');
if($this->bufferSize !== count($buffer)) throw new Exception('Supplied buffer is not the same size as defined FFT.');
$halfSize = 1;
for($i = 0; $i < $this->bufferSize; $i++){
$this->real[$i] = $buffer[$this->reverseTable[$i]];
$this->imag[$i] = 0;
}
while($halfSize < $this->bufferSize){
$phaseShiftReal = $this->cosTable[$halfSize];
$phaseShiftImag = $this->sinTable[$halfSize];
$currentPhaseShiftReal = 1;
$currentPhaseShiftImag = 0;
for($fftStep = 0; $fftStep < $halfSize; $fftStep++){
while($fftStep < $this->bufferSize){
$off = $fftStep + $halfSize;
$tr = ($currentPhaseShiftReal * $this->real[$off]) - ($currentPhaseShiftImag * $this->imag[$off]);
$ti = ($currentPhaseShiftReal * $this->imag[$off]) + ($currentPhaseShiftImag * $this->real[$off]);
$this->real[$off] = $this->real[$fftStep] - $tr;
$this->imag[$off] = $this->imag[$fftStep] - $ti;
$this->real[$fftStep] += $tr;
$this->imag[$fftStep] += $ti;
$fftStep += $halfSize << 1;
}
$tmpReal = $currentPhaseShiftReal;
$currentPhaseShiftReal = ($tmpReal * $phaseShiftReal) - ($currentPhaseShiftImag * $phaseShiftImag);
$currentPhaseShiftImag = ($tmpReal * $phaseShiftImag) + ($currentPhaseShiftImag * $phaseShiftReal);
}
$halfSize = $halfSize << 1;
}
$this->calculateSpectrum();
}
}
?>
The test sample is a sine wave at 440Hz.
When I tried to run the code, it throws this error
Notice: Undefined offset: 0 in C:\Program Files
(x86)\EasyPHP-12.1\www\fft.php on line 48
continuously.
The array that has problem has data like this:
Array
(
[1] => 512
[2] => 256
[3] => 768
[4] => 128
[5] => 640
[6] => 384
[7] => 896
[8] => 64
[9] => 576
[10] => 320
[11] => 832
[12] => 192
[13] => 704
[14] => 448
[15] => 960
[16] => 32
[17] => 544
[18] => 288
[19] => 800
[20] => 160
[21] => 672
[22] => 416
[23] => 928
[24] => 96
[25] => 608
[26] => 352
[27] => 864
[28] => 224
[29] => 736
[30] => 480
[31] => 992
[32] => 16
[33] => 528
[34] => 272
[35] => 784
[36] => 144
[37] => 656
[38] => 400
[39] => 912
[40] => 80
[41] => 592
[42] => 336
[43] => 848
[44] => 208
[45] => 720
...
[978] => 303
[979] => 815
[980] => 175
[981] => 687
[982] => 431
[983] => 943
[984] => 111
[985] => 623
[986] => 367
[987] => 879
[988] => 239
[989] => 751
[990] => 495
[991] => 1007
[992] => 31
[993] => 543
[994] => 287
[995] => 799
[996] => 159
[997] => 671
[998] => 415
[999] => 927
[1000] => 95
[1001] => 607
[1002] => 351
[1003] => 863
[1004] => 223
[1005] => 735
[1006] => 479
[1007] => 991
[1008] => 63
[1009] => 575
[1010] => 319
[1011] => 831
[1012] => 191
[1013] => 703
[1014] => 447
[1015] => 959
[1016] => 127
[1017] => 639
[1018] => 383
[1019] => 895
[1020] => 255
[1021] => 767
[1022] => 511
[1023] => 1023
)
Edit: The previous problem is solved but now another problem is raised. At function forward() it throws an uncaught exception Invalid buffer size, must be a power of 2. Even if the buffer size is right.
Any help will be appreciated.
Assuming that this is the whole class, I presume that the issue lies on this line inside your FFT constructor:
$this->reverseTable[$i + $limit] = $this->reverseTable[$i] + $bit;
From what I can tell you declare reverseTable as an array, but this line is the only place in the class where any elements are added to that array, so the fact that you're setting the reverseTable[$i+$limit] element using a never-defined reverseTable[$i] value is going to give you problems in the first first iteration of that while loop when it tries to use the undefined index $i (reverseTable[$i]). You'll have to give reverseTable[0] a value before you enter that loop.
Although you didn't provide where the line was, my guess is it has something to do with this line:
$this->reverseTable[$i + $limit] = $this->reverseTable[$i] + $bit;
This is in your constructor, and this bit especially looks wrong $this->reverseTable[$i] + $bit;. You are asking for the value from the reverseTable array, but this key is not initialized anywhere in the constructor.
I am not sure how to fix this, as it is a logic error on your part.
I'm trying to find each missing number in an array like the following.
Array (
[0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6 [6] => 7 [7] => 8
[8] => 9 [9] => 10 [10] => 11 [11] => 12 [12] => 13 [13] => 14 [14] => 15
[15] => 16 [16] => 17 [17] => 18 [18] => 19 [19] => 20 [20] => 21 [21] => 22
[22] => 23 [23] => 24 [24] => 25 [25] => 26 [26] => 27 [27] => 28 [28] => 29
[29] => 30 [30] => 31 [31] => 32 [32] => 33 [33] => 34 [34] => 35 [35] => 36
[36] => 37 [37] => 38 [38] => 39 [39] => 40 [40] => 41 [41] => 42 [42] => 43
[43] => 44 [44] => 45 [45] => 46 [46] => 47 [47] => 48 [48] => 49 [49] => 50
[50] => 51 [51] => 52 [52] => 53 [53] => 54 [54] => 55 [55] => 56 [56] => 57
[57] => 58 [58] => 59 [59] => 60 [60] => 61 [61] => 62 [62] => 63 [63] => 64
[64] => 67 [65] => 68 [66] => 69
)
The numbers 65,66 are missing in this particular array.
My question how do I figure out which numbers are missing with the help of PHP. Specifically what I need to find out is the lowest missing number.
Why: Because then I can assign that number to a member as an id.
You can make use of array_diff and range functions as:
// given array. 3 and 6 are missing.
$arr1 = array(1,2,4,5,7);
// construct a new array:1,2....max(given array).
$arr2 = range(1,max($arr1));
// use array_diff to get the missing elements
$missing = array_diff($arr2,$arr1); // (3,6)
I'm assuming the number is the element, not the key, of the array. I'm also assuming that the numbers start from 1, not 0.
$Expected = 1;
foreach ($InputArray as $Key => $Number)
{
if ($Expected != $Number)
{
break;
}
$Expected++;
}
echo $Number;
For big sorted arrays of unique numbers, you can binary search the array for either the lowest or highest unused number. Cost=Log2N. Example: 65536 items can be searched in 16 loops since
if ( arr[hi] - arr[lo] > hi - lo )
... there are unused numbers in that range ...
So (I don't know PHP, but it can be translated...):
lo = first entry index
hi = last entry index
if ( arr[hi] - arr[lo] == hi - lo )
return arr[hi]+1; // no gaps so return highest + 1
do
{
mid = (lo + hi) / 2;
if ( arr[mid] - arr[lo] > mid - lo ) // there is a gap in the bottom half somewhere
hi = mid; // search the bottom half
else
lo = mid; // search the top half
} while ( hi > lo + 1 ); // search until 2 left
return arr[lo]+1;
If given input is not in sorted order and size of input is very large then we can use following logic in any programming language:
Algorithm
bring smaller chunk into memory from large input
initialize three variables say min = 0, max = 0 and missingIds = []
scan smaller chunked input from left to right
if scannedValue found in missingIds
then,
pop scannedValue from missingIds
go to next value;
If scanned value is near to min
then,
find all the missing numbers between scannedValue and min, push into missingIds
min = scannedValue;
Else if scanned value is near to max
then,
find all the missing numbers between scannedValue and max, push into missingIds
max = scannedValue;
repeat above steps until large input scanned from left to right
Example in PHP
<?php
$largeInput = [40,41,42,43,44,45,1,2,3,4,5,6,7,8,9,10,11,12,13,14,35,36,37,38,39,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,67,68,69,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34];
$missingIds = [];
$min = 0;
$max = 0;
$chunkSize = 10;
$chunkNo = 0;
$currentInput = array_slice($largeInput, $chunkNo, $chunkSize);
while(count($currentInput) > 0) {
foreach($currentInput as $id) {
if(in_array($id,$missingIds)) {
$missingIds = array_diff($missingIds,[$id]);
continue;
}
if($id <= $min) {
$distMin = $min - $id;
if($distMin > 2) {
$tempArr = range($id+1,$min-1);
$missingIds = array_merge($missingIds, $tempArr);
$tempArr = [];
} else if ($distMin > 1) {
$tempArr = [$id+1];
$missingIds = array_merge($missingIds, $tempArr);
$tempArr = [];
}
$min = $id;
} else if ($id >= $max){
$distMax = $id - $max;
if($distMax > 2) {
$tempArr = range($max+1,$id-1);
$missingIds = array_merge($missingIds, $tempArr);
$tempArr = [];
} else if ($distMax > 1) {
$tempArr = [$max+1];
$missingIds = array_merge($missingIds, $tempArr);
$tempArr = [];
}
$max = $id;
}
}
$chunkNo++;
$currentInput = array_slice($largeInput, $chunkNo, $chunkSize);
}
print_r($missingIds);
//$idArrayMissing = array([0] => 1, [1] => 2, [2] => 4, [3] => 5, [4] => 6, [5] => 7);
$idArrayMissing = array(1, 2, 4, 5, 6, 7);
//$idArrayFull = array([0] => 1, [1] => 2, [2] => 3, [3] => 4, [4] => 5, [5] => 6);
$idArrayFull = array(1, 2, 3, 4, 5, 6);
function gap($arr)
{
while (list($k, $v) = each($arr))
if ($k != ($v-1))
return $k;
return -1;
}
print "ok:" . gap($idArrayMissing) . "<br/>\n";
print "full:" . gap($idArrayFull) . "<br/>\n";
The return of the gap function can be 2 values:
-1 could indicate that the array has been traversed and there are no free slots or
$k+1 which could indicate that the first free slot is on the end of the array.
It can also be done easily by using in_array() function like this:
// lets say $InputArray has all the data
// lets declare a variable which we will search inside the $InputArray array and lets initialize it with either 0 or 1 or with the minimum value found inside $InputArray
$start_counting = 1;
$max_value = count($InputArray);
if (!(in_array($start_counting, $InputArray)))
{
echo "Value: ".$start_counting." is missing!"."<br>" ;
}
else{
if($start_counting <= $max_value -1)
{$start_counting++;}
}
else if($start_counting > $max_value -1)
{
echo "All missing numbers printed!"
}
}