File Coverage

blib/lib/Acme/Tools.pm
Criterion Covered Total %
statement 1233 1742 70.7
branch 636 1126 56.4
condition 306 602 50.8
subroutine 179 263 68.0
pod 142 186 76.3
total 2496 3919 63.6


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2             package Acme::Tools;
3              
4             our $VERSION = '0.172'; #new version: C-s ny versjon
5              
6 28     28   643398 use 5.008; #Perl 5.8 was released July 18th 2002
  28         107  
7 28     28   155 use strict;
  28         51  
  28         656  
8 28     28   133 use warnings;
  28         54  
  28         866  
9 28     28   148 use Carp;
  28         44  
  28         9224  
10              
11             require Exporter;
12             our @ISA = qw(Exporter);
13             our %EXPORT_TAGS = ( all => [ qw() ] );
14             our @EXPORT_OK = ( @{ $EXPORT_TAGS{all} } );
15             our @EXPORT = qw(
16             min
17             max
18             mins
19             maxs
20             sum
21             avg
22             geomavg
23             harmonicavg
24             stddev
25             median
26             percentile
27             $Resolve_iterations
28             $Resolve_last_estimate
29             resolve
30             resolve_equation
31             conv
32             rank
33             rankstr
34             eqarr
35             sorted
36             sortedstr
37             pushsort
38             pushsortstr
39             binsearch
40             binsearchstr
41             random
42             random_gauss
43             big
44             bigi
45             bigf
46             bigr
47             bigscale
48             nvl
49             repl
50             replace
51             decode
52             decode_num
53             between
54             curb bound
55             distinct
56             in
57             in_num
58             uniq
59             union
60             union_all
61             minus
62             minus_all
63             intersect
64             intersect_all
65             not_intersect
66             mix
67             zip
68             subhash
69             hashtrans
70             zipb64
71             zipbin
72             unzipb64
73             unzipbin
74             gzip
75             gunzip
76             bzip2
77             bunzip2
78             ipaddr
79             ipnum
80             webparams
81             urlenc
82             urldec
83             ht2t
84             chall
85             makedir
86             qrlist
87             ansicolor
88             ccn_ok
89             KID_ok
90             writefile
91             readfile
92             readdirectory
93             basename
94             dirname
95             wipe
96             username
97             range
98             permutations
99             trigram
100             sliding
101             chunks
102             chars
103             cart
104             reduce
105             int2roman
106             roman2int
107             num2code
108             code2num
109             gcd
110             lcm
111             pivot
112             tablestring
113             upper
114             lower
115             trim
116             rpad
117             lpad
118             cpad
119             dserialize
120             serialize
121             srlz
122             bytes_readable
123             distance
124             tms
125             easter
126             time_fp
127             sleep_fp
128             sleeps
129             sleepms
130             sleepus
131             sleepns
132             eta
133             sys
134             recursed
135             md5sum
136             pwgen
137             read_conf
138             openstr
139             ldist
140             $Re_isnum
141             isnum
142             part
143             parth
144             parta
145             ed
146             $Edcursor
147             brainfu
148             brainfu2perl
149             brainfu2perl_optimized
150             bfinit
151             bfsum
152             bfaddbf
153             bfadd
154             bfcheck
155             bfgrep
156             bfgrepnot
157             bfdelete
158             bfstore
159             bfretrieve
160             bfclone
161             bfdimensions
162             $PI
163             install_acme_command_tools
164              
165             $Dbh
166             dlogin
167             dlogout
168             drow
169             drows
170             drowc
171             drowsc
172             dcols
173             dpk
174             dsel
175             ddo
176             dins
177             dupd
178             ddel
179             dcommit
180             drollback
181             );
182              
183             our $PI = '3.141592653589793238462643383279502884197169399375105820974944592307816406286';
184              
185             =head1 NAME
186              
187             Acme::Tools - Lots of more or less useful subs lumped together and exported into your namespace
188              
189             =head1 SYNOPSIS
190              
191             use Acme::Tools;
192              
193             print sum(1,2,3); # 6
194             print avg(2,3,4,6); # 3.75
195              
196             my @list = minus(\@listA, \@listB); # set operations
197             my @list = union(\@listA, \@listB); # set operations
198              
199             print length(gzip("abc" x 1000)); # far less than 3000
200              
201             writefile("/dir/filename",$string); # convenient
202             my $s=readfile("/dir/filename"); # also conventient
203              
204             print "yes!" if between($pi,3,4);
205              
206             print percentile(0.05, @numbers);
207              
208             my @even = range(1000,2000,2); # even numbers between 1000 and 2000
209             my @odd = range(1001,2001,2);
210              
211             my $dice = random(1,6);
212             my $color = random(['red','green','blue','yellow','orange']);
213              
214             ...and more.
215              
216             =encoding utf8
217              
218             =head1 ABSTRACT
219              
220             About 120 more or less useful perl subroutines lumped together and exported into your namespace.
221              
222             =head1 DESCRIPTION
223              
224             Subs created and collected since the mid-90s.
225              
226             =head1 INSTALLATION
227              
228             sudo cpan Acme::Tools
229             sudo cpanm Acme::Tools # after: sudo apt-get install cpanminus make # for Ubuntu 12.04
230              
231             =head1 EXPORT
232              
233             Almost every sub, about 90 of them.
234              
235             Beware of namespace pollution. But what did you expect from an Acme module?
236              
237             =head1 NUMBERS
238              
239             =head2 num2code
240              
241             See L
242              
243             =head2 code2num
244              
245             C convert numbers (integers) from the normal decimal system to some arbitrary other number system.
246             That can be binary (2), oct (8), hex (16) or others.
247              
248             Example:
249              
250             print num2code(255,2,"0123456789ABCDEF"); # prints FF
251             print num2code( 14,2,"0123456789ABCDEF"); # prints 0E
252              
253             ...because 255 are converted to hex FF (base C<< length("0123456789ABCDEF") >> ) which is 2 digits of 0-9 or A-F.
254             ...and 14 are converted to 0E, with leading 0 because of the second argument 2.
255              
256             Example:
257              
258             print num2code(1234,16,"01")
259              
260             Prints the 16 binary digits 0000010011010010 which is 1234 converted to binary zeros and ones.
261              
262             To convert back:
263              
264             print code2num("0000010011010010","01"); #prints 1234
265              
266             C can be used to compress numeric IDs to something shorter:
267              
268             $chars="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_";
269             print num2code("241274432",5,$chars); # prints EOOv0
270             print code2num("EOOv0",$chars); # prints 241274432
271              
272             =cut
273              
274             #Math::BaseCnv
275              
276             sub num2code {
277 4     4 1 495 my($num,$digits,$validchars,$start)=@_;
278 4         8 my $l=length($validchars);
279 4         6 my $key;
280 28     28   149 no warnings;
  28         49  
  28         188058  
281 4 50       14 croak if $num<$start;
282 4         7 $num-=$start;
283 4         12 for(1..$digits){
284 25         49 $key=substr($validchars,$num%$l,1).$key;
285 25         44 $num=int($num/$l);
286             }
287 4 50       11 croak if $num>0;
288 4         17 return $key;
289             }
290              
291             sub code2num {
292 1 50   1 1 4 my($code,$validchars,$start)=@_; $start=0 if !defined $start;
  1         5  
293 1         2 my $l=length($validchars);
294 1         2 my $num=0;
295 1         14 $num=$num*$l+index($validchars,$_) for split//,$code;
296 1         7 return $num+$start;
297             }
298              
299              
300             =head2 gcd
301              
302             I< C<">The Euclidean algorithm (also called Euclid's algorithm) is an
303             algorithm to determine the greatest common divisor (gcd) of two
304             integers. It is one of the oldest algorithms known, since it appeared
305             in the classic Euclid's Elements around 300 BC. The algorithm does not
306             require factoring.C<"> >
307              
308             B two or more positive numbers (integers, without decimals that is)
309              
310             B an integer
311              
312             B
313              
314             print gcd(12, 8); # prints 4
315              
316             Because the (prime number) factors of 12 is 2 * 2 * 3 and the factors of 8 is 2 * 2 * 2
317             and the common ('overlapping') factors for both 12 and 8 is then 2 * 2 and the result becomes 4.
318              
319             B:
320              
321             print gcd(90, 135, 315); # prints 45
322             print gcd(2*3*3*5, 3*3*3*5, 3*3*5*7); # prints 45 ( = 3*3*5 which is common to all three args)
323              
324             Implementation:
325              
326             sub gcd { my($a,$b,@r)=@_; @r ? gcd($a,gcd($b,@r)) : $b==0 ? $a : gcd($b, $a % $b) }
327              
328             L
329              
330             L
331              
332             =cut
333              
334 26 100   26 1 406 sub gcd { my($a,$b,@r)=@_; @r ? gcd($a,gcd($b,@r)) : $b==0 ? $a : gcd($b, $a % $b) }
  26 100       101  
335              
336             =head2 lcm
337              
338             C finds the Least Common Multiple of two or more numbers (integers).
339              
340             B two or more positive numbers (integers)
341              
342             B an integer number
343              
344             Example: C< 2/21 + 1/6 = 4/42 + 7/42 = 11/42>
345              
346             Where 42 = lcm(21,6).
347              
348             B
349              
350             print lcm(45,120,75); # prints 1800
351              
352             Because the factors are:
353              
354             45 = 2^0 * 3^2 * 5^1
355             120 = 2^3 * 3^1 * 5^1
356             75 = 2^0 * 3^1 * 5^2
357              
358             Take the bigest power of each primary number (2, 3 and 5 here).
359             Which is 2^3, 3^2 and 5^2. Multiplied this is 8 * 9 * 25 = 1800.
360              
361             sub lcm { my($a,$b,@r)=@_; @r ? lcm($a,lcm($b,@r)) : $a*$b/gcd($a,$b) }
362              
363             Seems to works with L as well: (C of all integers from 1 to 200)
364              
365             perl -MAcme::Tools -MMath::BigInt -le'print lcm(map Math::BigInt->new($_),1..200)'
366              
367             337293588832926264639465766794841407432394382785157234228847021917234018060677390066992000
368              
369             =cut
370              
371 3 100   3 1 8 sub lcm { my($a,$b,@r)=@_; @r ? lcm($a,lcm($b,@r)) : $a*$b/gcd($a,$b) }
  3         16  
372              
373             =head2 resolve
374              
375             Resolves an equation by Newtons method.
376              
377             B 1-6 arguments. At least one argument.
378              
379             First argument: must be a coderef to a subroutine (a function)
380              
381             Second argument: if present, the target, f(x)=target. Default 0.
382              
383             Third argument: a start position for x. Default 0.
384              
385             Fourth argument: a small delta value. Default 1e-4 (0.0001).
386              
387             Fifth argument: a maximum number of iterations before resolve gives up
388             and carps. Default 100 (if fifth argument is not given or is
389             undef). The number 0 means infinite here. If the derivative of the
390             start position is zero or close to zero more iterations are typically
391             needed.
392              
393             Sixth argument: A number of seconds to run before giving up. If both
394             fifth and sixth argument is given and > 0, C stops at
395             whichever comes first.
396              
397             B returns the number C for C = 0
398              
399             ...or equal to the second input argument if present.
400              
401             B
402              
403             The equation C<< x^2 - 4x - 21 = 0 >> has two solutions: -3 and 7.
404              
405             The result of C will depend on the start position:
406              
407             print resolve { $_**2 - 4*$_ - 21 }; # -3 with $_ as your x
408             print resolve(sub{ my $x=shift; $x**2 - 4*$x - 21 }); # -3 more elaborate call
409             print resolve(sub{ my $x=shift; $x**2 - 4*$x - 21 },0,3); # 7 with start position 3
410             print "Iterations: $Acme::Tools::Resolve_iterations\n"; # 3 or larger, about 10-15 is normal
411              
412             The variable C< $Acme::Tools::Resolve_iterations > (which is exported) will be set
413             to the last number of iterations C used. Also if C dies (carps).
414              
415             The variable C< $Acme::Tools::Resolve_last_estimate > (which is exported) will be
416             set to the last estimate. This number will often be close to the solution and can
417             be used even if C dies (carps).
418              
419             B
420              
421             If either second, third or fourth argument is an instance of L, so will the result be:
422              
423             use Acme::Tools;
424             my $equation = sub{ $_ - 1 - 1/$_ };
425             my $gr1 = resolve( $equation, 0, 1 ); #
426             my $gr2 = resolve( $equation, 0, bigf(1) ); # 1/2 + sqrt(5)/2
427             bigscale(50);
428             my $gr3 = resolve( $equation, 0, bigf(1) ); # 1/2 + sqrt(5)/2
429            
430             print 1/2 + sqrt(5)/2, "\n";
431             print "Golden ratio 1: $gr1\n";
432             print "Golden ratio 2: $gr2\n";
433             print "Golden ratio 3: $gr3\n";
434              
435             Output:
436              
437             1.61803398874989
438             Golden ratio 1: 1.61803398874989
439             Golden ratio 2: 1.61803398874989484820458683436563811772029300310882395927211731893236137472439025
440             Golden ratio 3: 1.6180339887498948482045868343656381177203091798057610016490334024184302360920167724737807104860909804
441              
442             See:
443              
444             L
445              
446             L
447              
448             L
449              
450             TODO: fix fail for div by 0, e.g.:
451              
452             perl -MAcme::Tools -le'for(map$_/10,-4..20){printf"%9.4f %s\n",$_,3*$_+$_**4-12}print resolve(sub{$x=shift;3*$x+$x**4-12},0,1)'
453             resolve(sub{ my $x=shift; $x**2 - 4*$x - 21 },undef,1.9)
454             resolve_equation "x + 13*(3-x) = 17 - 1/x"
455              
456             =cut
457              
458             our $Resolve_iterations;
459             our $Resolve_last_estimate;
460              
461             #sub resolve(\[&$]@) {
462             sub resolve(&@) {
463 13     13 1 1177 my($f,$g,$start,$delta,$iters,$sec)=@_;
464 13 100       31 $g=0 if !defined $g;
465 13 100       26 $start=0 if !defined $start;
466 13 50       34 $delta=1e-4 if !defined $delta;
467 13 50       28 $iters=100 if !defined $iters;
468 13 100       27 $sec=0 if !defined $sec;
469 13 50       25 $iters=13e13 if $iters==0;
470 13 50 33     58 croak "Iterations ($iters) or seconds ($sec) can not be a negative number" if $iters<0 or $sec<0;
471 13         19 $Resolve_iterations=undef;
472 13         16 $Resolve_last_estimate=undef;
473 13 50       28 croak "Should have at least 1 argument, a coderef" if !@_;
474 13 50       33 croak "First argument should be a coderef" if ref($f) ne 'CODE';
475            
476 13         22 my @x=($start);
477 13 100       28 my $time_start=$sec>0?time_fp():undef;
478 13         21 my $timeout=0;
479 13 50       23 my $ds=ref($start) eq 'Math::BigFloat' ? Math::BigFloat->div_scale() : undef;
480             my $fx=sub{
481 546     546   743 local$_=$_[0];
482 546         1048 my $fx=&$f($_);
483 546 50 33     4142 if($fx=~/x/ and $fx=~/^[ \(\)\.\d\+\-\*\/x\=]+$/){
484 0         0 $fx=~s/^(.*)=(.*)$/($1)-($2)/;
485 0         0 $fx=~s,x,\$_,g;
486 0         0 $f=eval"sub{$fx}";
487 0         0 $fx=&$f($_);
488             }
489             $fx
490 13         50 };
  546         1365  
491 13         34 for my $n (0..$iters-1){
492 177         426 my $fd= &$fx($x[$n]+$delta*0.5) - &$fx($x[$n]-$delta*0.5);
493 177 100       423 $fd = &$fx($x[$n]+$delta*0.6) - &$fx($x[$n]-$delta*0.4) if $fd==0; #wiggle...
494 177 100       343 $fd = &$fx($x[$n]+$delta*0.3) - &$fx($x[$n]-$delta*0.7) if $fd==0;
495             #warn "n=$n fd=$fd\n";
496 177 100       532 croak "Div by zero: df(x) = $x[$n] at n'th iteration, n=$n" if $fd==0;
497 176         348 $Resolve_last_estimate=
498             $x[$n+1]=$x[$n]-(&$fx($x[$n])-$g)/($fd/$delta);
499 176         239 $Resolve_iterations=$n;
500 176 100 100     792 last if $n>3 and $x[$n+1]==$x[$n] and $x[$n]==$x[$n-1];
      100        
501 165 50 66     625 last if $n>3 and ref($x[$n+1]) eq 'Math::BigFloat' and substr($x[$n+1],0,$ds) eq substr($x[$n],0,$ds); #hm
      33        
502 165 100 100     433 croak "Could not resolve, perhaps too little time given ($sec), iteratons=$n"
      100        
503             if $sec>0 and time_fp()-$time_start>$sec and $timeout=1;
504             #warn "$n: ".$x[$n+1]."\n";
505             }
506 11 50       26 croak "Could not resolve, perhaps too few iterations ($iters)" if @x>=$iters;
507 11         116 return $x[-1];
508             }
509              
510             =head2 resolve_equation
511              
512             This prints 2:
513              
514             print resolve_equation "x + 13*(3-x) = 17 - x"
515              
516             A string containing at least one x is converted into a perl function.
517             Then x is found by using L. The string conversion is done by
518             replacing every x with $_ and if a C< = > char is present it converts
519             C< leftside = rightside > into C< (leftside) - (rightside) = 0 > which
520             is the default behaviour of L.
521              
522             =cut
523              
524             #sub resolve_equation { my $e=shift;$e=~s/x/\$_/g;$e=~s/(.*)=(.*)/($1)-($2)/;resolve sub{eval$e},@_ }
525 0     0 1 0 sub resolve_equation { my $e=shift;resolve sub{$e},@_ }
  0     0   0  
  0         0  
526              
527             =head2 conv
528              
529             Converts between:
530              
531             =over 4
532              
533             =item * units of measurement
534              
535             =item * number systems
536              
537             =item * currencies
538              
539             =back
540              
541             B
542              
543             print conv( 2000, "meters", "miles" ); #prints 1.24274238447467
544             print conv( 2.1, 'km', 'm'); #prints 2100
545             print conv( 70,"cm","in"); #prints 27.5590551181102
546             print conv( 4,"USD","EUR"); #prints 3.20481552905431 (depending on todays rates)
547             print conv( 4000,"b","kb"); #prints 3.90625 (1 kb = 1024 bytes)
548             print conv( 4000,"b","Kb"); #prints 4 (1 Kb = 1000 bytes)
549             print conv( 1000,"mb","kb"); #prints 1024000
550             print conv( 101010,"bin","roman"); #prints XLII
551             print conv( "DCCXLII","roman","oct"); #prints 1346
552              
553             B are:>
554              
555             Note: units starting with the symbol _ means that all metric
556             prefixes from yocto 10^-24 to yotta 10^+24 is supported, so _m means
557             km, mm, cm, µm and so on. And _N means kN, MN GN and so on.
558              
559             Note2: Many units have synonyms: m, meter, meters ...
560              
561             acceleration: g, g0, m/s2, mps2
562            
563             angle: binary_degree, binary_radian, brad, deg, degree, degrees,
564             gon, grad, grade, gradian, gradians, hexacontade, hour,
565             new_degree, nygrad, point, quadrant, rad, radian, radians,
566             sextant, turn
567            
568             area: a, ar, are, ares, bunder, ca, centiare, cho, cm2,
569             daa, decare, decares, deciare, dekar,
570             djerib, m2, dunam, dönüm, earths, feddan, ft2, gongqing, ha
571             ha, hectare, hectares, hektar, jerib, km2, m2, manzana,
572             mi2, mm2, mu, qing, rai, sotka,
573             sqcm, sqft, sqkm, sqm, sqmi, sqmm
574             stremmata, um2, µm2
575            
576             bytes: Eb, Gb, Kb, KiB, Mb, Pb, Tb, Yb, Zb, b, byte,
577             kb, kilobyte, mb, megabyte,
578             gb, gigabyte, tb, terabyte,
579             pb, petabyte, eb, exabyte,
580             zb, zettabyte, yb, yottabyte
581            
582             charge: As, C, _e, coulomb, e
583            
584             current: A, _A, N/m2
585            
586             energy: BTU, Btu, J, Nm, W/s, Wh, Wps, Ws, _J, _eV,
587             cal, calorie, calories, eV, electronvolt,
588             erg, ergs, foot-pound, foot-pounds, ftlb, joule, kWh,
589             kcal, kilocalorie, kilocalories,
590             newtonmeter, newtonmeters, th, thermie
591            
592             force: N, _N, dyn, dyne, dynes, lb, newton
593            
594             length: NM, _m, _pc, astronomical unit, au, chain, ft, furlong,
595             in, inch, inches, km, league, lightyear, ls, ly,
596             m, meter, meters, mi, mil, mile, miles,
597             nautical mile, nautical miles, nmi,
598             parsec, pc, planck, yard, yard_imperical, yd, Å, ångstrøm
599            
600             mass: Da, _eV, _g, bag, carat, ct, dwt, eV, electronvolt, g,
601             grain, grains, gram, grams, kilo, kilos, kt, lb, lb_av,
602             lb_t, lb_troy, lbs, ounce, ounce_av, ounce_troy, oz, oz_av, oz_t,
603             pennyweight, pound, pound_av, pound_metric, pound_troy, pounds,
604             pwt, seer, sl, slug, solar_mass, st, stone, t, tonn, tonne, tonnes, u, wey
605            
606             mileage: mpg, l/100km, l/km, l/10km, lp10km, l/mil, liter_pr_100km, liter_pr_km, lp100km
607              
608             money: AED, ARS, AUD, BGN, BHD, BND, BRL, BWP, CAD, CHF, CLP, CNY,
609             COP, CZK, DKK, EUR, GBP, HKD, HRK, HUF, IDR, ILS, INR, IRR,
610             ISK, JPY, KRW, KWD, KZT, LKR, LTL, LVL, LYD, MUR, MXN, MYR,
611             NOK, NPR, NZD, OMR, PHP, PKR, PLN, QAR, RON, RUB, SAR, SEK,
612             SGD, THB, TRY, TTD, TWD, USD, VEF, ZAR, BTC, LTC, mBTC, XBT
613             Currency rates are automatically updated from the net
614             at least every 24h since last update (on linux/cygwin).
615              
616             numbers: dec, hex, bin, oct, roman, dozen, doz, dz, dusin, gross, gro,
617             gr, great_gross, small_gross (not supported: decimal numbers)
618              
619             power: BTU, BTU/h, BTU/s, BTUph, GWhpy, J/s, Jps, MWhpy, TWhpy,
620             W, Whpy, _W, ftlb/min, ftlb/s, hk, hp, kWh/yr, kWhpy
621            
622             pressure: N/m2, Pa, _Pa, at, atm, bar, mbar, pascal, psi, torr
623            
624             radioactivity: Bq, becquerel, curie
625            
626             speed: _m/s, km/h, km/t, kmh, kmph, kmt, m/s, mi/h, mph, mps,
627             kn, knot, knots, kt, mach, machs, c, fps, ft/s, ftps
628            
629             temperature: C, F, K, celsius, fahrenheit, kelvin
630            
631             time: _s, biennium, century, d, day, days, decade, dy, fortnight,
632             h, hour, hours, hr, indiction, jubilee, ke, lustrum, m,
633             millennium, min, minute, minutes, mo, moment, mon, month,
634             olympiad, quarter, s, season, sec, second, seconds, shake,
635             tp, triennium, w, week, weeks, y, y365, ySI, ycommon,
636             year, years, ygregorian, yjulian, ysideral, ytropical
637            
638             volume: l, L, _L, _l, cm3, m3, ft3, in3, liter, liters, litre, litres,
639             gal, gallon, gallon_imp, gallon_uk, gallon_us, gallons,
640             pint, pint_imp, pint_uk, pint_us, tsp, tablespoon, teaspoon,
641             floz, floz_uk, therm, thm, fat, bbl, Mbbl, MMbbl, drum
642              
643             See: L
644              
645             =cut
646              
647             #TODO: @arr2=conv(\@arr1,"from","to") # is way faster than:
648             #TODO: @arr2=map conv($_,"from","to"),@arr1
649             #TODO: conv(123456789,'b','h'); # h converts to something human-readable
650              
651             our %conv=(
652             length=>{
653             m => 1,
654             _m => 1,
655             meter => 1,
656             meters => 1,
657             km => 1000,
658             mil => 10000, #scandinavian #also: inch/1000!
659             in => 0.0254,
660             inch => 0.0254,
661             inches => 0.0254,
662             ft => 0.0254*12, #0.3048 m
663             feet => 0.0254*12, #0.3048 m
664             yd => 0.0254*12*3, #0.9144 m
665             yard => 0.0254*12*3, #0.9144 m
666             yards => 0.0254*12*3, #0.9144 m
667             fathom => 0.0254*12*3*2, #1.8288 m
668             fathoms => 0.0254*12*3*2, #1.8288 m
669             chain => 0.0254*12*3*22, #20.1168 m
670             chains => 0.0254*12*3*22, #20.1168 m
671             furlong => 0.0254*12*3*22*10, #201.168 m
672             furlongs=> 0.0254*12*3*22*10, #201.168 m
673             mi => 0.0254*12*3*22*10*8, #1609.344 m
674             mile => 0.0254*12*3*22*10*8, #1609.344 m
675             miles => 0.0254*12*3*22*10*8,
676             league => 0.0254*12*3*22*10*8*3, #4828.032 m
677             leagues => 0.0254*12*3*22*10*8*3, #4828.032 m
678             yard_imperical => 0.914398416,
679             NM => 1852, #nautical mile
680             nmi => 1852, #nautical mile
681             'nautical mile' => 1852,
682             'nautical miles' => 1852,
683             'Å' => 1e-10,
684             'ångstrøm' => 1e-10,
685             ly => 299792458*3600*24*365.25,
686             lightyear => 299792458*3600*24*365.25, # = 9460730472580800 by def
687             ls => 299792458, #light-second
688             pc => 3.0857e16, #3.26156 ly
689             _pc => 3.0857e16, #3.26156 ly
690             parsec => 3.0857e16,
691             au => 149597870700, # by def, earth-sun
692             'astronomical unit' => 149597870700,
693             planck => 1.61619997e-35, #planck length
694             #Norwegian (old) lengths:
695             tomme => 0.0254,
696             tommer => 0.0254,
697             fot => 0.0254*12, #0.3048m
698             alen => 0.0254*12*2, #0.6096m
699             favn => 0.0254*12*2*3, #1.8288m
700             kvart => 0.0254*12*2/4, #0.1524m a quarter alen
701             },
702             mass =>{ #https://en.wikipedia.org/wiki/Unit_conversion#Mass
703             g => 1,
704             _g => 1,
705             gram => 1,
706             grams => 1,
707             kilo => 1000,
708             kilos => 1000,
709             t => 1000000,
710             tonn => 1000000,
711             tonne => 1000000,
712             tonnes => 1000000,
713             seer => 933.1,
714             lb => 453.59237,
715             lbs => 453.59237,
716             lb_av => 453.59237,
717             lb_t => 373.2417216, #5760 grains
718             lb_troy => 373.2417216,
719             pound => 453.59237,
720             pounds => 453.59237,
721             pound_av => 453.59237,
722             pound_troy => 373.2417216,
723             pound_metric => 500,
724             ounce => 28, # US food, 28g
725             ounce_av => 453.59237/16, # avoirdupois lb/16 = 28.349523125g
726             ounce_troy => 31.1034768, # lb_troy / 12
727             oz => 28, # US food, 28g
728             oz_av => 453.59237/16, # avoirdupois lb/16 = 28.349523125g
729             oz_t => 31.1034768, # lb_troy / 12,
730             grain => 64.79891/1000, # 453.59237/7000
731             grains => 64.79891/1000,
732             pennyweight => 31.1034768 / 20,
733             pwt => 31.1034768 / 20,
734             dwt => 31.1034768 / 20,
735             st => 6350.29318, # 14 lb_av
736             stone => 6350.29318,
737             wey => 114305.27724, # 252 lb = 18 stone
738             carat => 0.2,
739             ct => 0.2, #carat (metric)
740             kt => 64.79891/1000 * (3+1/6), #carat/karat
741             u => 1.66053892173e-30, #atomic mass carbon-12
742             Da => 1.66053892173e-30, #atomic mass carbon-12
743             slug => 14600,
744             sl => 14600,
745             eV => 1.783e-33, #e=mc2
746             _eV => 1.783e-33,
747             electronvolt => 1.783e-33,
748             'solar mass' => 1.99e33,
749             solar_mass => 1.99e33,
750             bag => 60*1000, #60kg coffee
751             },
752             area =>{ # https://en.wikipedia.org/wiki/Unit_conversion#Area
753             m2 => 1,
754             dm2 => 0.1**2,
755             cm2 => 0.01**2,
756             mm2 => 0.001**2,
757             'µm2' => 1e-6**2,
758             um2 => 1e-6**2,
759             sqm => 1,
760             sqcm => 0.01**2,
761             sqmm => 0.001**2,
762             km2 => 1000**2,
763             sqkm => 1000**2,
764             a => 100,
765             ar => 100,
766             are => 100,
767             ares => 100,
768             dekar => 1000,
769             decare => 1000,
770             decares => 1000,
771             daa => 1000,
772             'mål' => 1000,
773             ha => 10000,
774             hektar => 10000,
775             hectare => 10000,
776             hectares=> 10000,
777             ft2 => (0.0254*12)**2,
778             sqft => (0.0254*12)**2,
779             mi2 => 1609.344**2,
780             sqmi => 1609.344**2,
781             yd2 => (0.0254*12*3)**2, #square yard
782             sqyd => (0.0254*12*3)**2,
783             yard2 => (0.0254*12*3)**2,
784             sqyard => (0.0254*12*3)**2,
785             rood => 1210*(0.0254*12)**2, # 1/4 acres
786             roods => 1210*(0.0254*12)**2, # 1/4 acres
787             ac => 4840*(0.0254*12)**2, # 4840 square yards
788             acre => 4840*(0.0254*12)**2,
789             acres => 4840*(0.0254*12)**2,
790             homestead => 4840*(0.0254*12)**2 *160, #160 acres US Surveyors or 1/4 sqmiles
791             township => 4840*(0.0254*12)**2 *160*144, #144 homesteads or 36 sqmiles
792             perches => 4840*(0.0254*12)**2 /160, #160 perches = 1 acre in sri lanka
793             sotka => 100, #russian are
794             jerib => 10000, #iran hectare
795             djerib => 10000, #turkish hectare
796             gongqing => 10000, #chinese hectare
797             manzana => 10000, #argentinian hectare
798             bunder => 10000, #dutch hectare
799             centiare => 1,
800             deciare => 10,
801             ca => 1,
802             mu => 10000/15, #China
803             qing => 10000/0.15, #China
804             dunam => 10000/10, #Middle East
805             'dönüm' => 10000/10, #Middle East
806             stremmata =>10000/10, #Greece
807             rai => 10000/6.25, #Thailand
808             cho => 10000/1.008, #Japan
809             feddan => 10000/2.381, #Egypt
810             earths => 510072000*1000**2, #510072000 km2, surface area of earth
811             barn => 1e-28, #physics
812             outhouse => 1e-34, #physics
813             shed => 1e-52, #physics
814             },
815             volume=>{
816             l => 1,
817             L => 1,
818             _L => 1,
819             _l => 1,
820             liter => 1,
821             liters => 1,
822             litre => 1,
823             litres => 1,
824             gal => 231*2.54**3/1000, #3.785411784, #231 cubic inches
825             gallon => 231*2.54**3/1000,
826             gallons => 231*2.54**3/1000,
827             gallon_us => 231*2.54**3/1000,
828             gallon_uk => 4.54609,
829             gallon_imp=> 4.54609,
830             gallon_us_dry => 4.40488377086, # ~ 9.25**2*pi*2.54**3/1000 L
831             m3 => 10**3, #1000 L
832             cm3 => 0.1**3, #0.001 L
833             in3 => 0.254**3, #0.016387064 L
834             ft3 => (0.254*12)**3,
835             tablespoon=> 3.785411784/256, #14.78676478125 mL
836             tsp => 3.785411784/256/3, #4.92892159375 mL
837             teaspoon => 3.785411784/256/3, #4.92892159375 mL
838             floz => 3.785411784/128, #fluid ounce US
839             floz_uk => 4.54609/160, #fluid ounce UK
840             pint => 4.54609/8, #0.56826125 L
841             pint_uk => 4.54609/8,
842             pint_imp => 4.54609/8,
843             pint_us => 3.785411784/8, #0.473176473
844             therm => 2.74e3, #? 100000BTUs? (!= thermie)
845             thm => 2.74e3, #? (!= th)
846             fat => 42*231*2.54**3/1000,
847             bbl => 42*231*2.54**3/1000, #oil barrel ~159 liters https://en.wikipedia.org/wiki/Barrel_(unit)
848             Mbbl => 42*231*2.54**3, #mille (thousand) oil barrels
849             MMbbl => 42*231*2.54**3*1000, #mille mille (million) oil barrels
850             drum => 200,
851             #Norwegian:
852             meterfavn => 2 * 2 * 0.6, #ved 2.4 m3
853             storfavn => 2 * 2 * 3, #ved 12 m3
854             },
855             time =>{
856             s => 1,
857             _s => 1,
858             sec => 1,
859             second => 1,
860             seconds => 1,
861             m => 60,
862             min => 60,
863             minute => 60,
864             minutes => 60,
865             h => 60*60,
866             hr => 60*60,
867             hour => 60*60,
868             hours => 60*60,
869             d => 60*60*24,
870             dy => 60*60*24,
871             day => 60*60*24,
872             days => 60*60*24,
873             w => 60*60*24*7,
874             week => 60*60*24*7,
875             weeks => 60*60*24*7,
876             mo => 60*60*24 * 365.2425/12,
877             mon => 60*60*24 * 365.2425/12,
878             month => 60*60*24 * 365.2425/12,
879             quarter => 60*60*24 * 365.2425/12 * 3, #3 months
880             season => 60*60*24 * 365.2425/12 * 3, #3 months
881             y => 60*60*24 * 365.2425, # 365+97/400 #97 leap yers in 400 years
882             year => 60*60*24 * 365.2425,
883             years => 60*60*24 * 365.2425,
884             yjulian => 60*60*24 * 365.25, # 365+1/4
885             y365 => 60*60*24 * 365, # finance/science
886             ycommon => 60*60*24 * 365, # finance/science
887             ygregorian => 60*60*24 * 365.2425, # 365+97/400
888             #ygaussian => 365+(6*3600+9*60+56)/(24*3600), # 365+97/400
889             ytropical => 60*60*24 * 365.24219,
890             ysideral => 365.256363004,
891             ySI => 60*60*24*365.25, #31556925.9747
892             decade => 10 * 60*60*24*365.2425,
893             biennium => 2 * 60*60*24*365.2425,
894             triennium => 3 * 60*60*24*365.2425,
895             olympiad => 4 * 60*60*24*365.2425,
896             lustrum => 5 * 60*60*24*365.2425,
897             indiction => 15 * 60*60*24*365.2425,
898             jubilee => 50 * 60*60*24*365.2425,
899             century => 100 * 60*60*24*365.2425,
900             millennium => 1000 * 60*60*24*365.2425,
901             shake => 1e-8,
902             moment => 3600/40, #1/40th of an hour, used by Medieval Western European computists
903             ke => 864, #1/100th of a day, trad Chinese, 14m24s
904             fortnight => 14*24*3600,
905             tp => 5.3910632e-44, #planck time, time for ligth to travel 1 planck length
906             },
907             speed=>{
908             'm/s' => 1,
909             '_m/s' => 1,
910             mps => 1,
911             mph => 1609.344/3600,
912             'mi/h' => 1609.344/3600,
913             kmh => 1/3.6,
914             kmph => 1/3.6,
915             'km/h' => 1/3.6,
916             kmt => 1/3.6, # t=time or temps (scandinavian and french and dutch)
917             'km/t' => 1/3.6,
918             kn => 1852/3600,
919             kt => 1852/3600,
920             knot => 1852/3600,
921             knop => 1852/3600, #scandinavian
922             knots => 1852/3600,
923             c => 299792458, #speed of light
924             mach => 340.3, #speed of sound
925             machs => 340.3,
926             fps => 0.3048, #0.0254*12
927             ftps => 0.3048,
928             'ft/s' => 0.3048,
929             },
930             acceleration=>{
931             'm/s2' => 1,
932             'mps2' => 1,
933             g => 9.80665,
934             g0 => 9.80665,
935             #0-100kmh or ca 0-60 mph x seconds...
936             },
937             temperature=>{ #http://en.wikipedia.org/wiki/Temperature#Conversion
938             C=>1, F=>1, K=>1, celsius=>1, fahrenheit=>1, kelvin=>1
939             },
940             radioactivity=>{
941             Bq => 1,
942             becquerel => 1,
943             curie => 3.7e10,
944             },
945             current=> {
946             A => 1,
947             _A => 1,
948             'N/m2' => 2e-7,
949             },
950             charge=>{
951             e => 1,
952             _e => 1,
953             C => 6.24150964712042e+18,
954             coulomb => 6.24150964712042e+18,
955             As => 6.24150964712042e+18,
956             #Faraday unit of charge ???
957             },
958             power=> {
959             W => 1,
960             _W => 1,
961             'J/s' => 1,
962             Jps => 1,
963             hp => 746,
964             hk => 746, #hestekrefter (norwegian, scandinavian)
965             'kWh/yr' => 1000 * 3600/(24*365), #kWh annually
966             Whpy => 3600/(24*365), #kWh annually
967             kWhpy => 1000 * 3600/(24*365), #kWh annually
968             MWhpy => 1000**2 * 3600/(24*365), #kWh annually
969             GWhpy => 1000**3 * 3600/(24*365), #kWh annually
970             TWhpy => 1000**4 * 3600/(24*365), #kWh annually
971             BTU => 1055.05585262/3600, #
972             BTUph => 1055.05585262/3600,
973             'BTU/h' => 1055.05585262/3600,
974             'BTU/s' => 1055.05585262,
975             'ftlb/s' => 746/550,
976             'ftlb/min'=> 746/550/60,
977             },
978             energy=>{
979             joule => 1,
980             J => 1,
981             _J => 1,
982             Ws => 1,
983             Wps => 1,
984             'W/s' => 1,
985             Nm => 1,
986             newtonmeter => 1,
987             newtonmeters => 1,
988             Wh => 3600,
989             kWh => 3600000, #3.6 million J
990             cal => 4.1868, # ~ 3600/860
991             calorie => 4.1868,
992             calories => 4.1868,
993             kcal => 4.1868*1000,
994             kilocalorie => 4.1868*1000,
995             kilocalories => 4.1868*1000,
996             BTU => 4.1868 * 252, # = 1055.0736 or is 1055.05585262 right?
997             Btu => 4.1868 * 252,
998             ftlb => 746/550, # ~ 1/0.7375621
999             'foot-pound' => 746/550,
1000             'foot-pounds' => 746/550,
1001             erg => 1e-7,
1002             ergs => 1e-7,
1003             eV => 1.60217656535e-19,
1004             _eV => 1.60217656535e-19,
1005             electronvolt => 1.60217656535e-19,
1006             thermie => 4.1868e6,
1007             th => 4.1868e6,
1008             },
1009             force=> {
1010             newton=> 1,
1011             N => 1,
1012             _N => 1,
1013             dyn => 1e-5,
1014             dyne => 1e-5,
1015             dynes => 1e-5,
1016             lb => 4.448222,
1017             },
1018             pressure=>{
1019             Pa => 1,
1020             _Pa => 1,
1021             pascal => 1,
1022             'N/m2' => 1,
1023             bar => 100000.0,
1024             mbar => 100.0,
1025             at => 98066.5, #technical atmosphere
1026             atm => 101325.0, #standard atmosphere
1027             torr => 133.3224,
1028             psi => 6894.8, #pounds per square inch
1029             },
1030             bytes=> {
1031             b => 1,
1032             kb => 1024, #2**10
1033             mb => 1024**2, #2**20 = 1048576
1034             gb => 1024**3, #2**30 = 1073741824
1035             tb => 1024**4, #2**40 = 1099511627776
1036             pb => 1024**5, #2**50 = 1.12589990684262e+15
1037             eb => 1024**6, #2**60 =
1038             zb => 1024**7, #2**70 =
1039             yb => 1024**8, #2**80 =
1040             KiB => 1024, #2**10
1041             KiB => 1024**2, #2**20 = 1048576
1042             KiB => 1024**3, #2**30 = 1073741824
1043             KiB => 1024**4, #2**40 = 1099511627776
1044             KiB => 1024**5, #2**50 = 1.12589990684262e+15
1045             KiB => 1024**6, #2**60 =
1046             KiB => 1024**7, #2**70 =
1047             KiB => 1024**8, #2**80 =
1048             Kb => 1000, #2**10
1049             Mb => 1000**2, #2**20 = 1048576
1050             Gb => 1000**3, #2**30 = 1073741824
1051             Tb => 1000**4, #2**40 = 1099511627776
1052             Pb => 1000**5, #2**50 = 1.12589990684262e+15
1053             Eb => 1000**6, #2**60 =
1054             Zb => 1000**7, #2**70 =
1055             Yb => 1000**8, #2**80 =
1056             byte => 1,
1057             kilobyte => 1024, #2**10
1058             megabyte => 1024**2, #2**20 = 1048576
1059             gigabyte => 1024**3, #2**30 = 1073741824
1060             terabyte => 1024**4, #2**40 = 1099511627776
1061             petabyte => 1024**5, #2**50 = 1.12589990684262e+15
1062             exabyte => 1024**6, #2**60 =
1063             zettabyte => 1024**7, #2**70 =
1064             yottabyte => 1024**8, #2**80 =
1065             },
1066             milage=>{ #fuel consumption
1067             'l/mil' => 1,
1068             'l/10km' => 1,
1069             'lp10km' => 1,
1070             'l/km' => 10,
1071             'l/100km' => 1/10,
1072             lp100km => 1/10,
1073             liter_pr_100km => 1/10,
1074             liter_pr_km => 10,
1075             mpg => -23.5214584, #negative signals inverse
1076             },
1077             # light=> {
1078             # cd => 1,
1079             # candela => 1,
1080             # },
1081             # lumens
1082             # lux
1083             angle =>{
1084             turn => 1,
1085             rad => 1/(2*$PI), # 2 * pi
1086             radian => 1/(2*$PI), # 2 * pi
1087             radians => 1/(2*$PI), # 2 * pi
1088             deg => 1/360, # 4 * 90
1089             degree => 1/360, # 4 * 90
1090             degrees => 1/360, # 4 * 90
1091             grad => 1/400,
1092             gradian => 1/400,
1093             gradians => 1/400,
1094             grade => 1/400, #french revolutionary unit
1095             gon => 1/400,
1096             new_degree => 1/400,
1097             nygrad => 1/400, #scandinavian
1098             quadrant => 1/4,
1099             sextant => 1/6,
1100             hour => 1/24,
1101             point => 1/32, #used in navigation
1102             hexacontade => 1/60,
1103             binary_degree => 1/256,
1104             binary_radian => 1/256,
1105             brad => 1/256,
1106             },
1107             money =>{ # rates at dec 17 2015
1108             AED => 2.389117, #
1109             ARS => 0.895122, #
1110             AUD => 6.253619, #
1111             BGN => 4.847575, #
1112             BHD => 23.267384, #
1113             BND => 6.184624, #
1114             BRL => 2.260703, #
1115             BTC => 3910.932213547, #bitcoin
1116             BWP => 0.794654, #
1117             CAD => 6.289957, #
1118             CHF => 8.799974, #
1119             CLP => 0.012410, #
1120             CNY => 1.353406, #
1121             COP => 0.00262229, #
1122             CZK => 0.351171, #
1123             DKK => 1.271914, #
1124             EUR => 9.489926, #
1125             GBP => 13.069440, #
1126             HKD => 1.131783, #
1127             HRK => 1.240878, #
1128             HUF => 0.029947, #
1129             IDR => 0.00062471, #
1130             ILS => 2.254456, #
1131             INR => 0.132063, #
1132             IRR => 0.00029370, #
1133             ISK => 0.067245, #
1134             JPY => 0.071492, #
1135             KRW => 0.00739237, #
1136             KWD => 28.862497, #
1137             KZT => 0.027766, #
1138             LKR => 0.061173, #
1139             LTC => 31.78895354018, #litecoin
1140             LTL => 2.748472, #
1141             LVL => 13.503025, #
1142             LYD => 6.296978, #
1143             MUR => 0.240080, #
1144             MXN => 0.515159, #
1145             MYR => 2.032465, #
1146             NOK => 1.000000000, #norwegian kroner
1147             NPR => 0.084980, #
1148             NZD => 5.878331, #
1149             OMR => 22.795994, #
1150             PHP => 0.184839, #
1151             PKR => 0.083779, #
1152             PLN => 2.207243, #
1153             QAR => 2.409162, #
1154             RON => 2.101513, #
1155             RUB => 0.122991, #
1156             SAR => 2.339745, #
1157             SEK => 1.023591, #
1158             SGD => 6.184624, #
1159             THB => 0.242767, #
1160             TRY => 2.994338, #
1161             TTD => 1.374484, #
1162             TWD => 0.265806, #
1163             USD => 8.774159, #
1164             VEF => 1.395461, #
1165             ZAR => 0.576487, #
1166             XBT => 3910.932213547, # bitcoin
1167             mBTC => 3910.932213547, # bitcoin
1168             mXBT => 3910.932213547, # bitcoin
1169             },
1170             numbers =>{
1171             dec=>1,hex=>1,bin=>1,oct=>1,roman=>1, des=>1,#des: spelling error in v0.15-0.16
1172             dusin=>1,dozen=>1,doz=>1,dz=>1,gross=>144,gr=>144,gro=>144,great_gross=>12*144,small_gross=>10*12,
1173             }
1174             );
1175             our $conv_prepare_time=0;
1176             our $conv_prepare_money_time=0;
1177             sub conv_prepare {
1178 1     1 0 11 my %b =(da =>1e+1, h =>1e+2, k =>1e+3, M =>1e+6, G =>1e+9, T =>1e+12, P =>1e+15, E =>1e+18, Z =>1e+21, Y =>1e+24, H =>1e+27);
1179 1         8 my %big =(deca=>1e+1, hecto=>1e+2, kilo =>1e+3, mega =>1e+6, giga=>1e+9, tera=>1e+12, peta =>1e+15, exa =>1e+18, zetta=>1e+21, yotta=>1e+24, hella=>1e+27);
1180 1         9 my %s =(d =>1e-1, c =>1e-2, m =>1e-3,'µ' =>1e-6, u=>1e-6, n =>1e-9, p =>1e-12, f =>1e-15, a =>1e-18, z =>1e-21, y =>1e-24);
1181 1         7 my %small=(deci=>1e-1, centi=>1e-2, milli=>1e-3, micro =>1e-6, nano=>1e-9, pico=>1e-12, femto=>1e-15, atto=>1e-18, zepto=>1e-21, yocto=>1e-24);
1182             # myria=> 10000 #obsolete
1183             # demi => 1/2, double => 2 #obsolete
1184             # lakh => 1e5, crore => 1e7 #south asian
1185 1         12 my %x = (%s,%b);
1186 1         9 for my $type (keys%conv) {
1187 20         30 for(grep/^_/,keys%{$conv{$type}}) {
  20         267  
1188 15         29 my $c=$conv{$type}{$_};
1189 15         26 delete$conv{$type}{$_};
1190 15         22 my $unit=substr($_,1);
1191 15         556 $conv{$type}{$_.$unit}=$x{$_}*$c for keys%x;
1192             }
1193             }
1194 1         17 $conv_prepare_time=time();
1195             }
1196              
1197             our $Currency_rates_url = 'http://calthis.com/currency-rates';
1198             our $Currency_rates_expire = 6*3600;
1199             sub conv_prepare_money {
1200 0     0 0 0 eval {
1201 0         0 require LWP::Simple;
1202 0 0       0 my $td=$^O=~/^(?:linux|cygwin)$/?"/tmp":"/tmp"; #hm wrong!
1203 0         0 my $fn="$td/acme-tools-currency-rates.data";
1204 0 0 0     0 if( !-e$fn or time() - (stat($fn))[9] >= $Currency_rates_expire){
1205 0         0 LWP::Simple::getstore($Currency_rates_url,"$fn.$$.tmp"); # get ... see getrates.cmd
1206 0 0       0 die "nothing downloaded" if !-s"$fn.$$.tmp";
1207 0         0 rename "$fn.$$.tmp",$fn;
1208 0         0 chmod 0666,$fn;
1209             }
1210 0         0 my $d=readfile($fn);
1211 0         0 my %r=$d=~/^\s*([A-Z]{3}) +(\d+\.\d+)\b/gm;
1212 0         0 $r{lc($_)}=$r{$_} for keys%r;
1213             #warn serialize([minus([sort keys(%r)],[sort keys(%{$conv{money}})])],'minus'); #ARS,AED,COP,BWP,LVL,BHD,NPR,LKR,QAR,KWD,LYD,SAR,KZT,CLP,IRR,VEF,TTD,OMR,MUR,BND
1214             #warn serialize([minus([sort keys(%{$conv{money}})],[sort keys(%r)])],'minus'); #LTC,I44,BTC,BYR,TWI,NOK,XDR
1215 0 0       0 $conv{money}={%{$conv{money}},%r} if keys(%r)>20;
  0         0  
1216             };
1217 0 0       0 carp "conv: conv_prepare_money (currency conversion automatic daily updated rates) - $@\n" if $@;
1218 0         0 $conv{money}{"m$_"}=$conv{money}{$_}/1000 for qw/BTC XBT/;
1219 0         0 $conv_prepare_money_time=time();
1220 0         0 1; #not yet
1221             }
1222              
1223             sub conv {
1224 41     41 1 14271 my($num,$from,$to)=@_;
1225 41 50       103 croak "conf requires 3 args" if @_!=3;
1226 41 100       89 conv_prepare() if !$conv_prepare_time;
1227 41     82   152 my $types=sub{ my $unit=shift; [sort grep$conv{$_}{$unit}, keys%conv] };
  82         114  
  82         1498  
1228 41   33     81 my @types=map{ my $ru=$_; my $r;$r=&$types($_) and @$r and $$ru=$_ and last for ($$ru,uc($$ru),lc($$ru)); $r }(\$from,\$to);
  82   33     103  
  82   50     97  
  82         259  
  82         280  
1229 41         74 my @err=map "Unit ".[$from,$to]->[$_]." is unknown",grep!@{$types[$_]},0..1;
  82         150  
1230 41         92 my @type=intersect(@types);
1231 41 50       105 push @err, "from=$from and to=$to has more than one possible conversions: ".join(", ", @type) if @type>1;
1232             push @err, "from $from (".(join(",",@{$types[0]})||'?').") and "
1233 41 50 0     92 ."to $to (" .(join(",",@{$types[1]})||'?').") has no known common unit type.\n" if @type<1;
      0        
1234 41 50       83 croak join"\n",map"conv: $_",@err if @err;
1235 41         57 my $type=$type[0];
1236 41 50 66     114 conv_prepare_money() if $type eq 'money' and time() >= $conv_prepare_money_time + $Currency_rates_expire;
1237 41 100       89 return conv_temperature(@_) if $type eq 'temperature';
1238 34 100       78 return conv_numbers(@_) if $type eq 'numbers';
1239 29         46 my $c=$conv{$type};
1240 29         35 my($cf,$ct)=@{$conv{$type}}{$from,$to};
  29         70  
1241 29 100 100     188 my $r= $cf>0 && $ct<0 ? -$ct/$num/$cf
    100 66        
1242             : $cf<0 && $ct>0 ? -$cf/$num/$ct
1243             : $cf*$num/$ct;
1244             # print STDERR "$num $from => $to from=$ff to=$ft r=$r\n";
1245 29         178 return $r;
1246             }
1247              
1248             sub conv_temperature { #http://en.wikipedia.org/wiki/Temperature#Conversion
1249 7     7 0 32 my($t,$from,$to)=(shift(),map uc(substr($_,0,1)),@_);
1250 7 100       25 $from=~s/K/C/ and $t-=273.15;
1251             #$from=~s/R/F/ and $t-=459.67; #rankine
1252 7 100       21 return $t if $from eq $to;
1253 1     1   7 {CK=>sub{$t+273.15},
1254 3     3   23 FC=>sub{($t-32)*5/9},
1255 2     2   14 CF=>sub{$t*9/5+32},
1256 0     0   0 FK=>sub{($t-32)*5/9+273.15},
1257 6         126 }->{$from.$to}->();
1258             }
1259              
1260             sub conv_numbers {
1261 5     5 0 10 my($n,$fr,$to)=@_;
1262 5 0       41 my $dec=$fr eq 'dec' ? $n
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    100          
    50          
1263             :$fr eq 'hex' ? hex($n)
1264             :$fr eq 'oct' ? oct($n)
1265             :$fr eq 'bin' ? oct("0b$n")
1266             :$fr =~ /^(dusin|dozen|doz|dz)$/ ? $n*12
1267             :$fr =~ /^(gross|gr|gro)$/ ? $n*144
1268             :$fr eq 'great_gross' ? $n*12*144
1269             :$fr eq 'small_gross' ? $n*12*10
1270             :$fr eq 'skokk' ? $n*60 #norwegian unit
1271             :$fr eq 'roman' ? roman2int($n)
1272             :$fr eq 'des' ? $n
1273             :croak "Conv from $fr not supported yet";
1274 5 50       52 my $ret=$to eq 'dec' ? $dec
    100          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    50          
    50          
1275             :$to eq 'hex' ? sprintf("%x",$dec)
1276             :$to eq 'oct' ? sprintf("%o",$dec)
1277             :$to eq 'bin' ? sprintf("%b",$dec)
1278             :$to =~ /^(dusin|dozen|doz|dz)$/ ? $dec/12
1279             :$to =~ /^(gross|gr|gro)$/ ? $dec/144
1280             :$to eq 'great_gross' ? $dec/(12*144)
1281             :$to eq 'small_gross' ? $dec/(12*10)
1282             :$to eq 'skokk' ? $dec/60
1283             :$to eq 'roman' ? int2roman($dec)
1284             :$to eq 'des' ? $dec
1285             :croak "Conv to $to not suppoerted yet";
1286 5         34 $ret;
1287             }
1288             #http://en.wikipedia.org/wiki/Norwegian_units_of_measurement
1289              
1290              
1291             =head2 bytes_readable
1292              
1293             Input: a number
1294              
1295             Output:
1296              
1297             the number with a B behind if the number is less than 1000
1298              
1299             the number divided by 1024 with two decimals and "kB" behind if the number is less than 1024*1000
1300              
1301             the number divided by 1048576 with two decimals and "MB" behind if the number is less than 1024*1024*1000
1302              
1303             the number divided by 1073741824 with two decimals and "GB" behind if the number is less than 1024*1024*1024*1000
1304              
1305             the number divided by 1099511627776 with two decimals and "TB" behind otherwise
1306              
1307             Examples:
1308              
1309             print bytes_readable(999); # 999 B
1310             print bytes_readable(1000); # 1000 B
1311             print bytes_readable(1001); # 0.98 kB
1312             print bytes_readable(1024); # 1.00 kB
1313             print bytes_readable(1153433.6); # 1.10 MB
1314             print bytes_readable(1181116006.4); # 1.10 GB
1315             print bytes_readable(1209462790553.6); # 1.10 TB
1316             print bytes_readable(1088516511498.24*1000); # 990.00 TB
1317              
1318             =cut
1319              
1320             sub bytes_readable {
1321 7     7 1 4727 my $bytes=shift();
1322 7 50       34 return undef if !defined $bytes;
1323 7 100       55 return "$bytes B" if abs($bytes)<=2** 0*1000; #bytes
1324 5 100       52 return sprintf("%.2f kB",$bytes/2**10) if abs($bytes)<2**10*1000; #kilobyte
1325 4 100       37 return sprintf("%.2f MB",$bytes/2**20) if abs($bytes)<2**20*1000; #megabyte
1326 3 100       33 return sprintf("%.2f GB",$bytes/2**30) if abs($bytes)<2**30*1000; #gigabyte
1327 2 50       51 return sprintf("%.2f TB",$bytes/2**40) if abs($bytes)<2**40*1000; #terrabyte
1328 0         0 return sprintf("%.2f PB",$bytes/2**50); #petabyte, exabyte, zettabyte, yottabyte
1329             }
1330              
1331             =head2 int2roman
1332              
1333             Converts integers to roman numbers.
1334              
1335             B
1336              
1337             print int2roman(1234); # prints MCCXXXIV
1338             print int2roman(1971); # prints MCMLXXI
1339              
1340             (Adapted subroutine from Peter J. Acklam, jacklam(&)math.uio.no)
1341              
1342             I = 1
1343             V = 5
1344             X = 10
1345             L = 50
1346             C = 100 (centum)
1347             D = 500
1348             M = 1000 (mille)
1349              
1350             See also L.
1351              
1352             See L for more.
1353              
1354             =head2 roman2int
1355              
1356             roman2int("MCMLXXI") == 1971
1357              
1358             =cut
1359              
1360             #alternative algorithm: http://www.rapidtables.com/convert/number/how-number-to-roman-numerals.htm
1361             sub int2roman {
1362 1161     1161 1 9018 my($n,@p)=(shift,[],[1],[1,1],[1,1,1],[1,2],[2],[2,1],[2,1,1],[2,1,1,1],[1,3],[3]);
1363             !defined($n)? undef
1364             : !length($n) ? ""
1365             : int($n)!=$n ? croak"int2roman: $n is not an integer"
1366             : $n==0 ? ""
1367             : $n<0 ? "-".int2roman(-$n)
1368             : $n>3999 ? "M".int2roman($n-1000)
1369 1161 100       6219 : join'',@{[qw/I V X L C D M/]}[map{my$i=$_;map($_+5-$i*2,@{$p[$n/10**(3-$i)%10]})}(0..3)];
  913 100       6024  
  3652 100       4160  
  3652 50       3787  
  3652 100       11202  
    100          
1370             }
1371              
1372             sub roman2int {
1373 1017     1017 1 7468 my($r,$n,%c)=(shift,0,'',0,qw/I 1 V 5 X 10 L 50 C 100 D 500 M 1000/);
1374 1017 100 66     4307 $r=~s/^-//?-roman2int($r):
1375             $r=~s/(C?)([DM])|(X?)([LCDM])|(I?)([VXLCDM])|(I)|(.)/
1376             croak "roman2int: Invalid number $r" if $8;
1377             $n += $c{$2||$4||$6||$7} - $c{$1||$3||$5||''}; ''/eg && $n
1378             }
1379              
1380             #sub roman2int_slow {
1381             # my $r=shift;
1382             # $r=~s,^\-,, ? 0-roman2int($r)
1383             # : $r=~s,^M,,i ? 1000+roman2int($r)
1384             # : $r=~s,^CM,,i ? 900+roman2int($r)
1385             # : $r=~s,^D,,i ? 500+roman2int($r)
1386             # : $r=~s,^CD,,i ? 400+roman2int($r)
1387             # : $r=~s,^C,,i ? 100+roman2int($r)
1388             # : $r=~s,^XC,,i ? 90+roman2int($r)
1389             # : $r=~s,^L,,i ? 50+roman2int($r)
1390             # : $r=~s,^XL,,i ? 40+roman2int($r)
1391             # : $r=~s,^X,,i ? 10+roman2int($r)
1392             # : $r=~s,^IX,,i ? 9+roman2int($r)
1393             # : $r=~s,^V,,i ? 5+roman2int($r)
1394             # : $r=~s,^IV,,i ? 4+roman2int($r)
1395             # : $r=~s,^I,,i ? 1+roman2int($r)
1396             # : !length($r) ? 0
1397             # : croak "Invalid roman number $r";
1398             #}
1399              
1400             =head2 distance
1401              
1402             B the four decimal numbers of two GPS positions: latutude1, longitude1, latitude2, longitude2
1403              
1404             B the air distance in meters between the two points
1405              
1406             Calculation is done using the Haversine Formula for spherical distance:
1407              
1408             a = sin((lat2-lat1)/2)^2
1409             + sin((lon2-lon1)/2)^2 * cos(lat1) * cos(lat2);
1410              
1411             c = 2 * atan2(min(1,sqrt(a)),
1412             min(1,sqrt(1-a)))
1413              
1414             distance = c * R
1415              
1416             With earth radius set to:
1417              
1418             R = Re - (Re-Rp) * sin(abs(lat1+lat2)/2)
1419              
1420             Where C (equatorial radius) and C (polar radius).
1421              
1422             B
1423              
1424             my @oslo = ( 59.93937, 10.75135); # oslo in norway
1425             my @rio = (-22.97673, -43.19508); # rio in brazil
1426              
1427             printf "%.1f km\n", distance(@oslo,@rio)/1000; # 10431.7 km
1428             printf "%.1f km\n", distance(@rio,@oslo)/1000; # 10431.7 km
1429             printf "%.1f nmi\n", distance(@oslo,@rio)/1852.000; # 5632.7 nmi (nautical miles)
1430             printf "%.1f miles\n",distance(@oslo,@rio)/1609.344; # 6481.9 miles
1431             printf "%.1f miles\n",conv(distance(@oslo,@rio),"meters","miles");# 6481.9 miles
1432              
1433             See L
1434              
1435             and L
1436              
1437             and L
1438              
1439             and L, but Acme::Tools::distance() is about 8 times faster.
1440              
1441             =cut
1442              
1443             our $Distance_factor = $PI / 180;
1444 0     0 0 0 sub acos { atan2( sqrt(1 - $_[0] * $_[0]), $_[0] ) }
1445             sub distance_great_circle {
1446 0     0 0 0 my($lat1,$lon1,$lat2,$lon2)=map $Distance_factor*$_, @_;
1447 0         0 my($Re,$Rp)=( 6378137.0, 6356752.3 ); #earth equatorial and polar radius
1448 0         0 my $R=$Re-($Re-$Rp)*sin(abs($lat1+$lat2)/2); #approx
1449 0         0 return $R*acos(sin($lat1)*sin($lat2)+cos($lat1)*cos($lat2)*cos($lon2-$lon1))
1450             }
1451              
1452             sub distance {
1453 4     4 1 1791 my($lat1,$lon1,$lat2,$lon2)=map $Distance_factor*$_, @_;
1454 4         1500 my $a= sin(($lat2-$lat1)/2)**2
1455             + sin(($lon2-$lon1)/2)**2 * cos($lat1) * cos($lat2);
1456 4 50       9 my $sqrt_a =sqrt($a); $sqrt_a =1 if $sqrt_a >1;
  4         12  
1457 4 50       8 my $sqrt_1ma=sqrt(1-$a); $sqrt_1ma=1 if $sqrt_1ma>1;
  4         10  
1458 4         34 my $c=2*atan2($sqrt_a,$sqrt_1ma);
1459 4         7 my($Re,$Rp)=( 6378137.0, 6356752.3 ); #earth equatorial and polar radius
1460 4         10 my $R=$Re-($Re-$Rp)*sin(abs($lat1+$lat2)/2); #approx
1461 4         21 return $c*$R;
1462             }
1463              
1464              
1465             =head2 big
1466              
1467             =head2 bigi
1468              
1469             =head2 bigf
1470              
1471             =head2 bigr
1472              
1473             =head2 bigscale
1474              
1475             big, bigi, bigf, bigr and bigscale are sometimes convenient shorthands for using
1476             C<< Math::BigInt->new() >>, C<< Math::BigFloat->new() >> and C<< Math::BigRat->new() >>
1477             (preferably with the GMP for faster calculations). Examples:
1478              
1479             my $num1 = big(3); #returns a new Math::BigInt-object
1480             my $num2 = big('3.0'); #returns a new Math::BigFloat-object
1481             my $num3 = big(3.0); #returns a new Math::BigInt-object
1482             my $num4 = big(3.1); #returns a new Math::BigFloat-object
1483             my $num5 = big('2/7'); #returns a new Math::BigRat-object
1484             my($i1,$f1,$i2,$f2) = big(3,'3.0',3.0,3.1); #returns the four new numbers, as the above four lines
1485             #uses wantarray
1486              
1487             print 2**200; # 1.60693804425899e+60
1488             print big(2)**200; # 1606938044258990275541962092341162602522202993782792835301376
1489             print 2**big(200); # 1606938044258990275541962092341162602522202993782792835301376
1490             print big(2**200); # 1606938044258990000000000000000000000000000000000000000000000
1491              
1492             print 1/7; # 0.142857142857143
1493             print 1/big(7); # 0 because of integer arithmetics
1494             print 1/big(7.0); # 0 because 7.0 is viewed as an integer
1495             print 1/big('7.0'); # 0.1428571428571428571428571428571428571429
1496             print 1/bigf(7); # 0.1428571428571428571428571428571428571429
1497             print bigf(1/7); # 0.142857142857143 probably not what you wanted
1498              
1499             print 1/bigf(7); # 0.1428571428571428571428571428571428571429
1500             bigscale(80); # for increased precesion (default is 40)
1501             print 1/bigf(7); # 0.14285714285714285714285714285714285714285714285714285714285714285714285714285714
1502              
1503             In C the characters C<< . >> and C<< / >> will make it return a
1504             Math::BigFloat- and Math::BigRat-object accordingly. Or else a Math::BigInt-object is returned.
1505              
1506             Instead of guessing, use C, C and C to return what you want.
1507              
1508             B Acme::Tools does not depend on Math::BigInt and
1509             Math::BigFloat and GMP, but these four big*-subs do (by C).
1510             To use big, bigi, bigf and bigr effectively you should
1511             install Math::BigInt::GMP and Math::BigFloat::GMP like this:
1512              
1513             sudo cpanm Math::BigFloat Math::GMP Math::BingInt::GMP # or
1514             sudo cpan Math::BigFloat Math::GMP Math::BingInt::GMP # or
1515             sudo yum install perl-Math-BigInt-GMP perl-Math-GMP # on RedHat, RHEL or
1516             sudo apt-get install libmath-bigint-gmp-perl libmath-gmp-perl # on Ubuntu or some other way
1517              
1518             Unless GMP is installed for perl like this, the Math::Big*-modules
1519             will fall back to using similar but slower built in modules. See: L
1520              
1521             =cut
1522              
1523             sub bigi {
1524 9 100   9 1 239 eval q(use Math::BigInt try=>"GMP") if !$INC{'Math/BigInt.pm'};
  2     2   30595  
  2         28441  
  2         281  
1525 9 100       27827 if (wantarray) { return (map Math::BigInt->new($_),@_) }
  2         12  
1526 7         32 else { return Math::BigInt->new($_[0]) }
1527             }
1528             sub bigf {
1529 7 100   7 1 1634 eval q(use Math::BigFloat try=>"GMP") if !$INC{'Math/BigFloat.pm'};
  2     2   36896  
  2         24380  
  2         607  
1530 7 100       1234 if (wantarray) { return (map Math::BigFloat->new($_),@_) }
  2         10  
1531 5         21 else { return Math::BigFloat->new($_[0]) }
1532             }
1533             sub bigr {
1534 17 100   17 1 15557 eval q(use Math::BigRat try=>"GMP") if !$INC{'Math/BigRat.pm'};
  2     2   2674  
  2         12382  
  2         509  
1535 17 100       1594 if (wantarray) { return (map Math::BigRat->new($_),@_) }
  7         30  
1536 10         35 else { return Math::BigRat->new($_[0]) }
1537             }
1538             sub big {
1539             wantarray
1540 12 50   12 1 5981 ? (map /\./ ? bigf($_) : /\// ? bigr($_) : bigi($_), @_)
    100          
    100          
    100          
    100          
1541             : $_[0]=~/\./ ? bigf($_[0]) : $_[0]=~/\// ? bigr($_[0]) : bigi($_[0]);
1542             }
1543             sub bigscale {
1544 4 100   4 1 3795 @_==1 or croak "bigscale requires one and only one argument";
1545 2         5 my $scale=shift();
1546 2 50       9 eval q(use Math::BigInt try=>"GMP") if !$INC{'Math/BigInt.pm'};
1547 2 50       7 eval q(use Math::BigFloat try=>"GMP") if !$INC{'Math/BigFloat.pm'};
1548 2 50       8 eval q(use Math::BigRat try=>"GMP") if !$INC{'Math/BigRat.pm'};
1549 2         10 Math::BigInt->div_scale($scale);
1550 2         38 Math::BigFloat->div_scale($scale);
1551 2         28 Math::BigRat->div_scale($scale);
1552 2         24 return;
1553             }
1554              
1555             #my $R_authalic=6371007.2; #earth radius in meters, mean, Authalic radius, real R varies 6353-6384km, http://en.wikipedia.org/wiki/Earth_radius
1556             #*)
1557             # ( 6378157.5, 6356772.2 ) #hmm
1558             #my $e=0.081819218048345;#sqrt(1 - $b**2/$a**2); #eccentricity of the ellipsoid
1559             #my($a,$b)=( 6378137.0, 6356752.3 ); #earth equatorial and polar radius
1560             #warn "e=$e\n";
1561             #warn "t=".(1 - $e**2)."\n";
1562             #warn "n=".((1 - $e**2 * sin(($lat1+$lat1)/2)**2)**1.5)."\n";
1563             #my $t=1 - $e**2;
1564             #my $n=(1 - $e**2 * sin(($lat1+$lat1)/2)**2)**1.5;
1565             #warn "t=$t\n";
1566             #warn "n=$n\n";
1567             #$a * (1 - $e**2) / ((1 - $e**2 * sin(($lat1+$lat2)/2)**2)**1.5); #hmm avg lat
1568             #$R=$a * $t/$n;
1569              
1570             #=head2 fractional
1571             #=cut
1572              
1573             sub fractional { #http://mathcentral.uregina.ca/QQ/database/QQ.09.06/h/lil1.html
1574 0     0 0 0 carp "fractional: NOT FINISHED";
1575 0         0 my $n=shift;
1576 0         0 print "----fractional n=$n\n";
1577 0         0 my $nn=$n; my $dec;
  0         0  
1578 0         0 $nn=~s,\.(\d+)$,$dec=length($1);$1.,;
1579 0         0 my $l;
1580 0         0 my $max=0;
1581 0         0 my($te,$ne);
1582 0         0 for(1..length($nn)/2){
1583 0 0       0 if( $nn=~/^(\d*?)((.{$_})(\3)+)$/ ){
1584 0         0 print "_ = $_ ".length($2)."\n";
1585 0 0       0 if(length($2)>$max){
1586 0         0 $l=$_;
1587 0         0 $te="$1$3"-$1;
1588 0         0 $max=length($2);
1589             }
1590             }
1591             }
1592 0 0 0     0 return fractional($n) if !$l and !recursed() and $dec>6 and substr($n,-1) and substr($n,-1)--;
      0        
      0        
      0        
1593 0         0 print "l=$l max=$max\n";
1594 0         0 $ne="9" x $l;
1595 0         0 print log($n),"\n";
1596 0     0   0 my $st=sub{print "status: ".($te/$ne)." n=$n ".($n/$te*$ne)."\n"};
  0         0  
1597 0         0 while($n/$te*$ne<0.99){ &$st(); $ne*=10 }
  0         0  
  0         0  
1598 0         0 while($te/$n/$ne<0.99){ &$st(); $te*=10 }
  0         0  
  0         0  
1599 0         0 &$st();
1600 0         0 while(1){
1601 0         0 my $d=gcd($te,$ne); print "gcd=$d\n";
  0         0  
1602 0 0       0 last if $d==1;
1603 0         0 $te/=$d; $ne/=$d;
  0         0  
1604             }
1605 0         0 &$st();
1606 0 0       0 wantarray ? ($te,$ne) : "$te/$ne"; #gcd()
1607             }
1608              
1609             =head2 isnum
1610              
1611             B String to be tested on regexp C<< /^ \s* [\-\+]? (?: \d*\.\d+ | \d+ ) (?:[eE][\-\+]?\d+)?\s*$/x >>. If no argument is given isnum checks C<< $_ >>.
1612              
1613             B True or false (1 or 0)
1614              
1615             =cut
1616              
1617             our $Re_isnum=qr/^ \s* [\-\+]? (?: \d*\.\d+ | \d+ ) (?:[eE][\-\+]?\d+)?\s*$/x;
1618 20 100   20 1 11390 sub isnum {(@_?$_[0]:$_)=~$Re_isnum}
1619              
1620             =head2 between
1621              
1622             Input: Three arguments.
1623              
1624             Returns: Something I if the first argument is numerically between the two next.
1625              
1626             =cut
1627              
1628             sub between {
1629 27     27 1 10924 my($test,$fom,$tom)=@_;
1630 28     28   208 no warnings;
  28         58  
  28         6396  
1631 27 100 66     488 return $fom<$tom ? $test>=$fom&&$test<=$tom
      33        
1632             : $test>=$tom&&$test<=$fom;
1633             }
1634              
1635             =head2 curb
1636              
1637             B Three arguments: value, minumum, maximum.
1638              
1639             B Returns the value if its between the given minumum and maximum.
1640             Returns minimum if the value is less or maximum if the value is more.
1641              
1642             my $v = 234;
1643             print curb( $v, 200, 250 ); #prints 234
1644             print curb( $v, 150, 200 ); #prints 200
1645             print curb( $v, 250, 300 ); #prints 250
1646             print curb(\$v, 250, 300 ); #prints 250 and changes $v
1647             print $v; #prints 250
1648              
1649             In the last example $v is changed because the argument is a reference. (To keep backward compatability, C<< bound() >> is a synonym for C<< curb() >>)
1650              
1651             =cut
1652              
1653             sub curb {
1654 129     129 1 1215 my($val,$min,$max)=@_;
1655 129 50 66     1631 croak "curb: wrong args" if @_!=3 or !defined$min or !defined$max or !defined$val or $min>$max;
      100        
      66        
      66        
1656 126 100       287 return $$val=curb($$val,$min,$max) if ref($val) eq 'SCALAR';
1657 125 100       339 $val < $min ? $min :
    100          
1658             $val > $max ? $max :
1659             $val;
1660             }
1661 0     0 0 0 sub bound { curb(@_) }
1662              
1663             =head1 STRINGS
1664              
1665             =head2 upper
1666              
1667             =head2 lower
1668              
1669             Returns input string as uppercase or lowercase.
1670              
1671             Can be used if Perls build in C and C for some reason does not convert æøå or other latin letters outsize a-z.
1672              
1673             Converts C<< æøåäëïöüÿâêîôûãõàèìòùáéíóúýñð >> to and from C<< ÆØÅÄËÏÖÜ?ÂÊÎÔÛÃÕÀÈÌÒÙÁÉÍÓÚÝÑÐ >>
1674              
1675             See also C<< perldoc -f uc >> and C<< perldoc -f lc >>
1676              
1677             =head2 trim
1678              
1679             Removes space from the beginning and end of a string. Whitespace (C<< \s >>) that is.
1680             And removes any whitespace inside the string of more than one char, leaving the first whitespace char. Thus:
1681              
1682             trim(" asdf \t\n 123 ") eq "asdf 123"
1683             trim(" asdf\t\n 123\n") eq "asdf\t123"
1684              
1685             Works on C<< $_ >> if no argument i given:
1686              
1687             print join",", map trim, " please ", " remove ", " my ", " spaces "; # please,remove,my,spaces
1688             print join",", trim(" please ", " remove ", " my ", " spaces "); # works on arrays as well
1689             my $s=' please '; trim(\$s); # now $s eq 'please'
1690             trim(\@untrimmedstrings); # trims array strings inplace
1691             @untrimmedstrings = map trim, @untrimmedstrings; # same, works on $_
1692             trim(\$_) for @untrimmedstrings; # same, works on \$_
1693              
1694             =head2 lpad
1695              
1696             =head2 rpad
1697              
1698             Left or right pads a string to the given length by adding one or more spaces at the end for I or at the start for I.
1699              
1700             B First argument: string to be padded. Second argument: length of the output. Optional third argument: character(s) used to pad.
1701             Default is space.
1702              
1703             rpad('gomle',9); # 'gomle '
1704             lpad('gomle',9); # ' gomle'
1705             rpad('gomle',9,'-'); # 'gomle----'
1706             lpad('gomle',9,'+'); # '++++gomle'
1707             rpad('gomle',4); # 'goml'
1708             lpad('gomle',4); # 'goml'
1709             rpad('gomle',7,'xyz'); # 'gomlxy'
1710             lpad('gomle',10,'xyz'); # 'xyzxygoml'
1711              
1712             =head2 cpad
1713              
1714             Center pads. Pads the string both on left and right equal to the given length. Centers the string. Pads right side first.
1715              
1716             cpad('mat',5) eq ' mat '
1717             cpad('mat',4) eq 'mat '
1718             cpad('mat',6) eq ' mat '
1719             cpad('mat',9) eq ' mat '
1720             cpad('mat',5,'+') eq '+mat+'
1721             cpad('MMMM',20,'xyzXYZ') eq 'xyzXYZxyMMMMxyzXYZxy'
1722              
1723             =cut
1724              
1725 28 50   28 1 156 sub upper {no warnings;my $s=@_?shift:$_;$s=~tr/a-zæøåäëïöüÿâêîôûãõàèìòùáéíóúýñð/A-ZÆØÅÄËÏÖÜÿÂÊÎÔÛÃÕÀÈÌÒÙÁÉÍÓÚÝÑÐ/;$s}
  28     1   66  
  28         2348  
  1         5  
  1         4  
  1         5  
1726 28 50   28 1 171 sub lower {no warnings;my $s=@_?shift:$_;$s=~tr/A-ZÆØÅÄËÏÖÜÿÂÊÎÔÛÃÕÀÈÌÒÙÁÉÍÓÚÝÑÐ/a-zæøåäëïöüÿâêîôûãõàèìòùáéíóúýñð/;$s}
  28     1   72  
  28         86147  
  1         4  
  1         3  
  1         6  
1727              
1728             sub trim {
1729 24 100   24 1 74 return trim($_) if !@_;
1730 20 100       50 return map trim($_), @_ if @_>1;
1731 19         28 my $s=shift;
1732 19 100       46 if(ref($s) eq 'SCALAR'){ $$s=~s,^\s+|(?<=\s)\s+|\s+$,,g; return $$s}
  5         25  
  5         14  
1733 14 100       31 if(ref($s) eq 'ARRAY') { trim(\$_) for @$s; return $s }
  1         4  
  1         3  
1734 13         94 $s=~s,^\s+|(?<=\s)\s+|\s+$,,g;
1735 13         63 $s;
1736             }
1737              
1738             sub rpad {
1739 4     4 1 795 my($s,$l,$p)=@_;
1740 4 100 66     20 $p=' ' if @_<3 or !length($p);
1741 4         23 $s.=$p while length($s)<$l;
1742 4         20 substr($s,0,$l);
1743             }
1744              
1745             sub lpad {
1746 5     5 1 1384 my($s,$l,$p)=@_;
1747 5 100 66     24 $p=' ' if @_<3 or !length($p);
1748 5 100       34 $l
1749             ? substr($s,0,$l)
1750             : substr($p x (1+$l/length($p)), 0, $l-length($s)).$s;
1751             }
1752              
1753             sub cpad {
1754 11     11 1 2894 my($s,$l,$p)=@_;
1755 11 100 66     48 $p=' ' if @_<3 or !length($p);
1756 11         16 my $ls=length($s);
1757 11 50       20 return substr($s,0,$l) if $l<$ls;
1758 11         29 $p=$p x (($l-$ls+2)/length($p));
1759 11         63 substr($p, 0, ($l-$ls )/2) . $s .
1760             substr($p, 0, ($l-$ls+1)/2);
1761             }
1762              
1763             sub cpad_old {
1764 0     0 0 0 my($s,$l,$p)=@_;
1765 0 0       0 $p=' ' if !length($p);
1766 0 0       0 return substr($s,0,$l) if $l
1767 0         0 my $i=0;
1768 0         0 while($l>length($s)){
1769 0 0       0 my $pc=substr($p,($i==int($i)?1:-1)*($i%length($p)),1);
1770 0 0       0 $i==int($i) ? ($s.=$pc) : ($s=$pc.$s);
1771 0         0 $i+=1/2;
1772             }
1773 0         0 $s;
1774             }
1775              
1776             =head2 trigram
1777              
1778             B A string (i.e. a name). And an optional x (see example 2)
1779              
1780             B A list of this strings trigrams (See examlpe)
1781              
1782             B
1783              
1784             print join ", ", trigram("Kjetil Skotheim");
1785              
1786             Prints:
1787              
1788             Kje, jet, eti, til, il , l S, Sk, Sko, kot, oth, the, hei, eim
1789              
1790             B
1791              
1792             Default is 3, but here 4 is used instead in the second optional input argument:
1793              
1794             print join ", ", trigram("Kjetil Skotheim", 4);
1795              
1796             And this prints:
1797              
1798             Kjet, jeti, etil, til , il S, l Sk, Sko, Skot, koth, othe, thei, heim
1799              
1800             C was created for "fuzzy" name searching. If you have a database of many names,
1801             addresses, phone numbers, customer numbers etc. You can use trigram() to search
1802             among all of those at the same time. If the search form only has one input field.
1803             One general search box.
1804              
1805             Store all of the trigrams of the trigram-indexed input fields coupled
1806             with each person, and when you search, you take each trigram of you
1807             query string and adds the list of people that has that trigram. The
1808             search result should then be sorted so that the persons with most hits
1809             are listed first. Both the query strings and the indexed database
1810             fields should have a space added first and last before C-ing
1811             them.
1812              
1813             This search algorithm is not includes here yet...
1814              
1815             C should perhaps have been named ngram for obvious reasons.
1816              
1817             =head2 sliding
1818              
1819             Same as trigram (except there is no default width). Works also with arrayref instead of string.
1820              
1821             Example:
1822              
1823             sliding( ["Reven","rasker","over","isen"], 2 )
1824              
1825             Result:
1826              
1827             ( ['Reven','rasker'], ['rasker','over'], ['over','isen'] )
1828              
1829             =head2 chunks
1830              
1831             Splits strings and arrays into chunks of given size:
1832              
1833             my @a = chunks("Reven rasker over isen",7);
1834             my @b = chunks([qw/Og gubben satt i kveldinga og koste seg med skillinga/], 3);
1835              
1836             Resulting arrays:
1837              
1838             ( 'Reven r', 'asker o', 'ver ise', 'n' )
1839             ( ['Og','gubben','satt'], ['i','kveldinga','og'], ['koste','seg','med'], ['skillinga'] )
1840              
1841             =head2 chars
1842              
1843             chars("Tittentei"); # ('T','i','t','t','e','n','t','e','i')
1844              
1845             =cut
1846              
1847 2   100 2 1 20 sub trigram { sliding($_[0],$_[1]||3) }
1848              
1849             sub sliding {
1850 3     3 1 6 my($s,$w)=@_;
1851 3 100       35 return map substr($s,$_,$w), 0..length($s)-$w if !ref($s);
1852 1 50       19 return map [@$s[$_..$_+$w-1]], 0..@$s-$w if ref($s) eq 'ARRAY';
1853             }
1854              
1855             sub chunks {
1856 2     2 1 6 my($s,$w)=@_;
1857 2 100       33 return $s=~/(.{1,$w})/g if !ref($s);
1858 1 50       14 return map [@$s[$_*$w .. min($_*$w+$w-1,$#$s)]], 0..$#$s/$w if ref($s) eq 'ARRAY';
1859             }
1860              
1861 0     0 1 0 sub chars { split//, shift }
1862              
1863             =head2 repl
1864              
1865             Synonym for replace().
1866              
1867             =head2 replace
1868              
1869             Return the string in the first input argument, but where pairs of search-replace strings (or rather regexes) has been run.
1870              
1871             Works as C in Oracle, or rather regexp_replace() in Oracle 10 and onward. Except that this C accepts more than three arguments.
1872              
1873             Examples:
1874              
1875             print replace("water","ater","ine"); # Turns water into wine
1876             print replace("water","ater"); # w
1877             print replace("water","at","eath"); # weather
1878             print replace("water","wa","ju",
1879             "te","ic",
1880             "x","y", # No x is found, no y is returned
1881             'r$',"e"); # Turns water into juice. 'r$' says that the r it wants
1882             # to change should be the last letters. This reveals that
1883             # second, fourth, sixth and so on argument is really regexs,
1884             # not normal strings. So use \ (or \\ inside "") to protect
1885             # the special characters of regexes. You probably also
1886             # should write qr/regexp/ instead of 'regexp' if you make
1887             # use of regexps here, just to make it more clear that
1888             # these are really regexps, not strings.
1889              
1890             print replace('JACK and JUE','J','BL'); # prints BLACK and BLUE
1891             print replace('JACK and JUE','J'); # prints ACK and UE
1892             print replace("abc","a","b","b","c"); # prints ccc (not bcc)
1893              
1894             If the first argument is a reference to a scalar variable, that variable is changed "in place".
1895              
1896             Example:
1897              
1898             my $str="test";
1899             replace(\$str,'e','ee','s','S');
1900             print $str; # prints teeSt
1901              
1902             =cut
1903              
1904 46     46 1 105 sub replace { repl(@_) }
1905             sub repl {
1906 69     69 1 142 my $str=shift;
1907 69 100       165 return $$str=replace($$str,@_) if ref($str) eq 'SCALAR';
1908             #return ? if ref($str) eq 'ARRAY';
1909             #return ? if ref($str) eq 'HASH';
1910 68         157 while(@_){
1911 82         153 my($fra,$til)=(shift,shift);
1912 82 100       5308 defined $til ? $str=~s/$fra/$til/g : $str=~s/$fra//g;
1913             }
1914 68         500 return $str;
1915             }
1916              
1917              
1918             =head1 ARRAYS
1919              
1920             =head2 min
1921              
1922             Returns the smallest number in a list. Undef is ignored.
1923              
1924             @lengths=(2,3,5,2,10,undef,5,4);
1925             $shortest = min(@lengths); # returns 2
1926              
1927             Note: The comparison operator is perls C<< < >>> which means empty strings is treated as C<0>, the number zero. The same goes for C, except of course C<< > >> is used instead.
1928              
1929             min(3,4,5) # 3
1930             min(3,4,5,undef) # 3
1931             min(3,4,5,'') # returns the empty string
1932              
1933             =head2 max
1934              
1935             Returns the largest number in a list. Undef is ignored.
1936              
1937             @heights=(123,90,134,undef,132);
1938             $highest = max(@heights); # 134
1939              
1940             =head2 mins
1941              
1942             Just as L, except for strings.
1943              
1944             print min(2,7,10); # 2
1945             print mins("2","7","10"); # 10
1946             print mins(2,7,10); # 10
1947              
1948             =head2 maxs
1949              
1950             Just as L, except for strings.
1951              
1952             print max(2,7,10); # 10
1953             print maxs("2","7","10"); # 7
1954             print maxs(2,7,10); # 7
1955              
1956             =cut
1957              
1958 35 100 100 35 1 1760 sub min {my $min;for(@_){ $min=$_ if defined($_) and !defined($min) || $_ < $min } $min }
  35   66     75  
  7087         31902  
  35         247  
1959 1 100 100 1 1 2 sub mins {my $min;for(@_){ $min=$_ if defined($_) and !defined($min) || $_ lt $min} $min }
  1   33     3  
  3         22  
  1         5  
1960 26 100 100 26 1 42 sub max {my $max;for(@_){ $max=$_ if defined($_) and !defined($max) || $_ > $max } $max }
  26   66     55  
  7069         32019  
  26         285  
1961 1 100 100 1 1 3 sub maxs {my $max;for(@_){ $max=$_ if defined($_) and !defined($max) || $_ gt $max} $max }
  1   33     3  
  3         22  
  1         4  
1962              
1963             =head2 zip
1964              
1965             B Two or more arrayrefs. A number of equal sized arrays
1966             containing numbers, strings or anything really.
1967              
1968             B An array of those input arrays zipped (interlocked, merged) into each other.
1969              
1970             print join " ", zip( [1,3,5], [2,4,6] ); # 1 2 3 4 5 6
1971             print join " ", zip( [1,4,7], [2,5,8], [3,6,9] ); # 1 2 3 4 5 6 7 8 9
1972              
1973             Example:
1974              
1975             zip() creates a hash where the keys are found in the first array and values in the secord in the correct order:
1976              
1977             my @media = qw/CD DVD VHS LP Blueray/;
1978             my @count = qw/20 12 2 4 3/;
1979             my %count = zip(\@media,\@count); # or zip( [@media], [@count] )
1980             print "I got $count{DVD} DVDs\n"; # I got 12 DVDs
1981              
1982             Dies (croaks) if the two lists are of different sizes
1983              
1984             ...or any input argument is not an array ref.
1985              
1986             =cut
1987              
1988             sub zip {
1989 7     7 1 74509 my @t=@_;
1990 7   66     328 ref($_) ne 'ARRAY' and croak "ERROR: zip should have arrayrefs as arguments" for @t;
1991 5   66     17 @{$t[$_]} != @{$t[0]} and croak "ERROR: zip should have equal sized arrays" for 1..$#t;
  5         8  
  5         215  
1992 3         5 my @res;
1993 3         5 for my $i (0..@{$t[0]}-1){
  3         8  
1994 9         28 push @res, $$_[$i] for @t;
1995             }
1996 3         21 return @res;
1997             }
1998              
1999              
2000             =head2 pushsort
2001              
2002             Adds one or more element to a numerically sorted array and keeps it sorted.
2003              
2004             pushsort @a, 13; # this...
2005             push @a, 13; @a = sort {$a<=>$b} @a; # is the same as this, but the former is faster if @a is large
2006              
2007             =head2 pushsortstr
2008              
2009             Same as pushsort except that the array is kept sorted alphanumerically (cmp) instead of numerically (<=>). See L.
2010              
2011             pushsort @a, "abc"; # this...
2012             push @a, "abc"; @a = sort @a; # is the same as this, but the former is faster if @a is large
2013              
2014             =cut
2015              
2016             our $Pushsort_cmpsub=undef;
2017             sub pushsort (\@@) {
2018 10915     10915 1 18082 my $ar=shift;
2019              
2020             #not needed but often faster
2021 10915 100 100     32419 if(!defined $Pushsort_cmpsub and @$ar+@_<100){ #hm speedup?
2022 2348         4690 @$ar=(sort {$a<=>$b} (@$ar,@_));
  51956         59714  
2023 2348         4684 return 0+@$ar;
2024             }
2025              
2026 8567         13067 for my $v (@_){
2027              
2028             #not needed but often faster
2029 7567 100       14284 if(!defined $Pushsort_cmpsub){ #faster rank() in most cases
2030 901 100 50     1837 push @$ar, $v and next if $v>=$$ar[-1];
2031 898 100 50     2047 unshift @$ar, $v and next if $v< $$ar[0];
2032             }
2033              
2034 7558         14327 splice @$ar, binsearch($v,$ar,1,$Pushsort_cmpsub)+1, 0, $v;
2035             }
2036 8567         16316 0+@$ar
2037             }
2038 0     0 1 0 sub pushsortstr(\@@){ local $Pushsort_cmpsub=sub{$_[0]cmp$_[1]}; pushsort(@_) } #speedup: copy sub pushsort
  1000     1000   3862  
  1000         2063  
2039              
2040             =head2 binsearch
2041              
2042             Returns the position of an element in a numerically sorted array. Returns undef if the element is not found.
2043              
2044             B Two, three or four arguments
2045              
2046             B the element to find. Usually a number.
2047              
2048             B a reference to the array to search in. The array
2049             should be sorted in ascending numerical order (se exceptions below).
2050              
2051             B Optional. Default false.
2052              
2053             If present, whether result I should return undef or a fractional position.
2054              
2055             If the third argument is false binsearcg returns undef if the element is not found.
2056              
2057             If the third argument is true binsearch returns 0.5 plus closest position below the searched value.
2058              
2059             Returns C< last position + 0.5 > if the searched element is greater than all elements in the sorted array.
2060              
2061             Returns C< -0.5 > if the searched element is less than all elements in the sorted array.
2062              
2063             Fourth argument: Optional. Default C<< sub { $_[0] <=> $_[1] } >>.
2064              
2065             If present, the fourth argument is a code-ref that alters the way binsearch compares two elements.
2066              
2067             B
2068              
2069             binsearch(10,[5,10,15,20]); # 1
2070             binsearch(10,[20,15,10,5],undef,sub{$_[1]<=>$_[0]}); # 2 search arrays sorted numerically in opposite order
2071             binsearch("c",["a","b","c","d"],undef,sub{$_[0]cmp$_[1]}); # 2 search arrays sorted alphanumerically
2072             binsearchstr("b",["a","b","c","d"]); # 1 search arrays sorted alphanumerically
2073              
2074             =head2 binsearchstr
2075              
2076             Same as binsearch except that the arrays is sorted alphanumerically
2077             (cmp) instead of numerically (<=>) and the searched element is a
2078             string, not a number. See L.
2079              
2080             =cut
2081              
2082             our $Binsearch_steps;
2083             our $Binsearch_maxsteps=100;
2084             sub binsearch {
2085 14603     14603 1 50019 my($search,$aref,$insertpos,$cmpsub)=@_; #search pos of search in array
2086 14603 50       33653 croak "binsearch did not get arrayref as second arg" if ref($aref) ne 'ARRAY';
2087 14603 50 66     42691 croak "binsearch got fourth arg which is not a code-ref" if $cmpsub and ref($cmpsub) ne 'CODE';
2088 14603 50       26570 return $insertpos ? -0.5 : undef if !@$aref;
    100          
2089 14591         20571 my($min,$max)=(0,$#$aref);
2090 14591         18924 $Binsearch_steps=0;
2091 14591         30175 while (++$Binsearch_steps <= $Binsearch_maxsteps) {
2092 128669         194631 my $middle=int(($min+$max+0.5)/2);
2093 128669         144580 my $middle_value=$$aref[$middle];
2094              
2095             #croak "binsearch got non-sorted array" if !$cmpsub and $$aref[$min]>$$aref[$min]
2096             # or $cmpsub and &$cmpsub($$aref[$min],$$aref[$min])>0;
2097              
2098 128669 100 100     748228 if( !$cmpsub and $search < $middle_value
    100 100        
      66        
      100        
      100        
      66        
2099             or $cmpsub and &$cmpsub($search,$middle_value) < 0 ) { #print "<\n";
2100 39065 50 66     92919 $max=$min, next if $middle == $max and $min != $max;
2101 39065 50       76541 return $insertpos ? $middle-0.5 : undef if $middle == $max;
    100          
2102 37589         80384 $max=$middle;
2103             }
2104             elsif( !$cmpsub and $search > $middle_value
2105             or $cmpsub and &$cmpsub($search,$middle_value) > 0 ) { #print ">\n";
2106 82567 100 100     209356 $min=$max, next if $middle == $min and $max != $min;
2107 75062 50       146964 return $insertpos ? $middle+0.5 : undef if $middle == $min;
    100          
2108 68984         156954 $min=$middle;
2109             }
2110             else { #print "=\n";
2111 7037         17279 return $middle;
2112             }
2113             }
2114 0         0 croak "binsearch exceded $Binsearch_maxsteps steps";
2115             }
2116              
2117             sub binsearchfast { # binary search routine finds index just below value
2118 0     0 0 0 my ($x,$v)=@_;
2119 0         0 my ($klo,$khi)=(0,$#{$x});
  0         0  
2120 0         0 my $k;
2121 0         0 while (($khi-$klo)>1) {
2122 0         0 $k=int(($khi+$klo)/2);
2123 0 0       0 if ($$x[$k]>$v) { $khi=$k; } else { $klo=$k; }
  0         0  
  0         0  
2124             }
2125 0         0 return $klo;
2126             }
2127              
2128              
2129 2     2 1 11 sub binsearchstr {binsearch(@_[0..2],sub{$_[0]cmp$_[1]})}
  1     1   9  
2130              
2131             =head2 rank
2132              
2133             B Two or three arguments. N and an arrayref for the list to look at.
2134              
2135             In scalar context: Returns the nth smallest number in an array. The array doesn't have to be sorted.
2136              
2137             In array context: Returns the n smallest numbers in an array.
2138              
2139             To return the n(th) largest number(s) instead of smallest, just negate n.
2140              
2141             An optional third argument can be a sub that is used to compare the elements of the input array.
2142              
2143             Examples:
2144              
2145             my $second_smallest = rank(2, [11,12,13,14]); # 12
2146             my @top10 = rank(-10, [1..100]); # 100, 99, 98, 97, 96, 95, 94, 93, 92, 91
2147             my $max = rank(-1, [101,102,103,102,101]); #103
2148             my @contest = ({name=>"Alice",score=>14},{name=>"Bob",score=>13},{name=>"Eve",score=>12});
2149             my $second = rank(2, \@contest, sub{$_[1]{score}<=>$_[0]{score}})->{name}; #Bob
2150              
2151             =head2 rankstr
2152              
2153             Just as C but sorts alphanumerically (strings, cmp) instead of numerically.
2154              
2155             =cut
2156              
2157             sub rank {
2158 35     35 1 498 my($rank,$aref,$cmpsub)=@_;
2159 35 100       77 if($rank<0){
2160 10   100 29957   45 $cmpsub||=sub{$_[0]<=>$_[1]};
  29957         146705  
2161 10     59997   43 return rank(-$rank,$aref,sub{0-&$cmpsub});
  59997         92764  
2162             }
2163 25         28 my @sort;
2164 25         35 local $Pushsort_cmpsub=$cmpsub;
2165 25         48 for(@$aref){
2166 8914         16135 pushsort @sort, $_;
2167 8914 100       23121 pop @sort if @sort>$rank;
2168             }
2169 25 100       1484 return wantarray ? @sort : $sort[$rank-1];
2170             }
2171 0 50   0 1 0 sub rankstr {wantarray?(rank(@_,sub{$_[0]cmp$_[1]})):rank(@_,sub{$_[0]cmp$_[1]})}
  60067     10   292870  
  10         61  
2172              
2173             =head2 eqarr
2174              
2175             B Two or more references to arrays.
2176              
2177             B True (1) or false (0) for whether or not the arrays are numerically I alphanumerically equal.
2178             Comparing each element in each array with both C< == > and C< eq >.
2179              
2180             Examples:
2181              
2182             eqarr([1,2,3],[1,2,3],[1,2,3]); # 1 (true)
2183             eqarr([1,2,3],[1,2,3],[1,2,4]); # 0 (false)
2184             eqarr([1,2,3],[1,2,3,4]); # undef (different size, false)
2185             eqarr([1,2,3]); # croak (should be two or more arrays)
2186             eqarr([1,2,3],1,2,3); # croak (not arraysrefs)
2187              
2188             =cut
2189              
2190             sub eqarr {
2191 27     27 1 491 my @arefs=@_;
2192 27 100       276 croak if @arefs<2;
2193 26   66     245 ref($_) ne 'ARRAY' and croak for @arefs;
2194 25   100     61 @{$arefs[0]} != @{$arefs[$_]} and return undef for 1..$#arefs;
  27         52  
  27         94  
2195 24         35 my $ant;
2196            
2197 24         75 for my $ar (@arefs[1..$#arefs]){
2198 26         60 for(0..@$ar-1){
2199 272 50 33     967 ++$ant and $ant>100 and croak ">100"; #TODO: feiler ved sammenligning av to tabeller > 10000(?) tall
2200 272 100 66     1284 return 0 if $arefs[0][$_] ne $$ar[$_]
2201             or $arefs[0][$_] != $$ar[$_];
2202             }
2203             }
2204 22         137 return 1;
2205             }
2206              
2207             =head2 sorted
2208              
2209             Return true if the input array is numerically sorted.
2210              
2211             @a=(1..10); print "array is sorted" if sorted @a; #true
2212              
2213             Optionally the last argument can be a comparison sub:
2214              
2215             @person=({Rank=>1,Name=>'Amy'}, {Rank=>2,Name=>'Paula'}, {Rank=>3,Name=>'Ruth'});
2216             print "Persons are sorted" if sorted @person, sub{$_[0]{Rank}<=>$_[1]{Rank}};
2217              
2218             =head2 sortedstr
2219              
2220             Return true if the input array is Inumerically sorted.
2221              
2222             @a=(1..10); print "array is sorted" if sortedstr @a; #false
2223             @a=("01".."10"); print "array is sorted" if sortedstr @a; #true
2224              
2225             =cut
2226              
2227             sub sorted (\@@) {
2228 4     4 1 13 my($a,$cmpsub)=@_;
2229 4         13 for(0..$#$a-1){
2230 1197 50 66     6421 return 0 if !$cmpsub and $$a[$_]>$$a[$_+1]
      66        
      33        
2231             or $cmpsub and &$cmpsub($$a[$_],$$a[$_+1])>0;
2232             }
2233 4         24 return 1;
2234             }
2235 99     99 1 797 sub sortedstr { sorted(@_,sub{$_[0]cmp$_[1]}) }
  2     2   17  
2236              
2237             =head2 part
2238              
2239             B A code-ref and a list
2240              
2241             B Two array-refs
2242              
2243             Like C but returns the false list as well. Partitions a list
2244             into two lists where each element goes into the first or second list
2245             whether the predicate (a code-ref) is true or false for that element.
2246              
2247             my( $odd, $even ) = part {$_%2} (1..8);
2248             print for @$odd; #prints 1 3 5 7
2249             print for @$even; #prints 2 4 6 8
2250              
2251             (Works like C< partition() > in the Scala programming language)
2252              
2253             =head2 parth
2254              
2255             Like C but returns any number of lists.
2256              
2257             B A code-ref and a list
2258              
2259             B A hash where the returned values from the code-ref are keys and the values are arrayrefs to the list elements which gave those keys.
2260              
2261             my %hash = parth { uc(substr($_,0,1)) } ('These','are','the','words','of','this','array');
2262             print serialize(\%hash);
2263              
2264             Result:
2265              
2266             %hash = ( T=>['These','the','this'],
2267             A=>['are','array'],
2268             O=>['of'],
2269             W=>['words'] )
2270              
2271             =head2 parta
2272              
2273             Like L but returns an array of lists.
2274              
2275             my @a = parta { length } qw/These are the words of this array/;
2276              
2277             Result:
2278              
2279             @a = ( undef, undef, ['of'], ['are','the'], ['this'], ['These','words','array'] )
2280              
2281             Two undefs at first (index positions 0 and 1) since there are no words of length 0 or 1 in the input array.
2282              
2283             =cut
2284              
2285 1 100   1 1 13 sub part (&@) { my($c,@r)=(shift,[],[]); push @{ $r[ &$c?0:1 ] }, $_ for @_; @r }
  1         4  
  8         42  
  1         6  
2286 1     1 1 258 sub parth (&@) { my($c,%r)=(shift); push @{ $r{ &$c } }, $_ for @_; %r }
  1         4  
  7         37  
  1         9  
2287 1     1 1 289 sub parta (&@) { my($c,@r)=(shift); push @{ $r[ &$c ] }, $_ for @_; @r }
  1         4  
  7         34  
  1         7  
2288              
2289             #sub mapn (&$@) { ... } like map but @_ contains n elems at a time, n=1 is map
2290              
2291             =head1 STATISTICS
2292              
2293             =head2 sum
2294              
2295             Returns the sum of a list of numbers. Undef is ignored.
2296              
2297             print sum(1,3,undef,8); # 12
2298             print sum(1..1000); # 500500
2299             print sum(undef); # undef
2300              
2301             =cut
2302              
2303 28   66 28 1 179 sub sum { my $sum; no warnings; defined($_) and $sum+=$_ for @_; $sum }
  28     45   56  
  28         2943  
  45         5074  
  45         16185  
  45         454  
2304              
2305             =head2 avg
2306              
2307             Returns the I number of a list of numbers. That is C
2308              
2309             print avg( 2, 4, 9); # 5 (2+4+9) / 3 = 5
2310             print avg( [2, 4, 9] ); # 5 pass by reference, same result but faster for large arrays
2311              
2312             Also known as I.
2313              
2314             Pass by reference: If one argument is given and it is a reference to an array,
2315             this array is taken as the list of numbers. This mode is about twice as fast
2316             for 10000 numbers or more. It most likely also saves memory.
2317              
2318             =cut
2319              
2320             sub avg {
2321 880     880 1 3568 my($sum,$n,@a)=(0,0);
2322 28     28   382 no warnings;
  28         54  
  28         14487  
2323 880 50       1740 if( @_==0 ) { return undef }
  0         0  
2324 880 100 100     2070 if( @_==1 and ref($_[0]) eq 'ARRAY' ){ @a=grep defined,@{$_[0]} }
  1         3  
  1         6  
2325 879         3942 else { @a=grep defined,@_ }
2326 880 100       1553 if( @a==0 ) { return undef }
  1         4  
2327 879         5597 $sum+=$_ for @a;
2328 879         3983 return $sum/@a
2329             }
2330              
2331             =head2 geomavg
2332              
2333             Returns the I (a.k.a I) of a list of numbers.
2334              
2335             print geomavg(10,100,1000,10000,100000); # 1000
2336             print 0+ (10*100*1000*10000*100000) ** (1/5); # 1000 same thing
2337             print exp(avg(map log($_),10,100,1000,10000,100000)); # 1000 same thing, this is how geomavg() works internally
2338              
2339             =cut
2340              
2341 771     771 1 3193 sub geomavg { exp(avg(map log($_), @_)) }
2342              
2343             =head2 harmonicavg
2344              
2345             Returns the I (a.k.a I) of a list of numbers. L
2346              
2347             print harmonicavg(10,11,12); # 3 / ( 1/10 + 1/11 + 1/12) = 10.939226519337
2348              
2349             =cut
2350              
2351 0     0 1 0 sub harmonicavg { my $s; $s+=1/$_ for @_; @_/$s }
  0         0  
  0         0  
2352              
2353             =head2 variance
2354              
2355             C<< variance = ( sum (x[i]-Average)**2)/(n-1) >>
2356              
2357             =cut
2358              
2359             sub variance {
2360 0     0 1 0 my $sumx2; $sumx2+=$_*$_ for @_;
  0         0  
2361 0         0 my $sumx; $sumx+=$_ for @_;
  0         0  
2362 0         0 (@_*$sumx2-$sumx*$sumx)/(@_*(@_-1));
2363             }
2364              
2365             =head2 stddev
2366              
2367             C<< Standard_Deviation = sqrt(variance) >>
2368              
2369             Standard deviation (stddev) is a measurement of the width of a normal
2370             distribution where one stddev on each side of the mean covers 68% and
2371             two stddevs 95%. Normal distributions are sometimes called Gauss curves
2372             or Bell shapes. L
2373              
2374             stddev(4,5,6,5,6,4,3,5,5,6,7,6,5,7,5,6,4) # = 1.0914103126635
2375             avg(@testscores) + stddev(@testscores) # = the score for IQ = 115 (by one definition)
2376             avg(@testscores) - stddev(@testscores) # = the score for IQ = 85
2377              
2378             =cut
2379              
2380             sub stddev {
2381 14 100   14 1 621 return undef if @_==0;
2382 13 100 66     72 return stddev(\@_) if @_>0 and !ref($_[0]);
2383 8         12 my $ar=shift;
2384 8 50       18 return undef if @$ar==0;
2385 8 100       24 return 0 if @$ar==1;
2386 6         6 my $sumx2; $sumx2 += $_*$_ for @$ar;
  6         105  
2387 6         6 my $sumx; $sumx += $_ for @$ar;
  6         68  
2388 6         38 sqrt( (@$ar*$sumx2-$sumx*$sumx)/(@$ar*(@$ar-1)) );
2389             }
2390              
2391             =head2 median
2392              
2393             Returns the median value of a list of numbers. The list do not have to
2394             be sorted.
2395              
2396             Example 1, list having an odd number of numbers:
2397              
2398             print median(1, 100, 101); # 100
2399              
2400             100 is the middlemost number after sorting.
2401              
2402             Example 2, an even number of numbers:
2403              
2404             print median(1005, 100, 101, 99); # 100.5
2405              
2406             100.5 is the average of the two middlemost numbers.
2407              
2408             =cut
2409              
2410             sub median {
2411 28     28   147 no warnings;
  28         48  
  28         14993  
2412 6     6 1 417 my @list = sort {$a<=>$b} @_;
  10035         11679  
2413 6         8 my $n=@list;
2414 6 100       217 $n%2 ? $list[($n-1)/2]
2415             : ($list[$n/2-1] + $list[$n/2])/2;
2416             }
2417              
2418              
2419             =head2 percentile
2420              
2421             Returns one or more percentiles of a list of numbers.
2422              
2423             Percentile 50 is the same as the I, percentile 25 is the first
2424             quartile, 75 is the third quartile.
2425              
2426             B
2427              
2428             First argument is your wanted percentile, or a refrence to a list of percentiles you want from the dataset.
2429              
2430             If the first argument to percentile() is a scalar, this percentile is returned.
2431              
2432             If the first argument is a reference to an array, then all those percentiles are returned as an array.
2433              
2434             Second, third, fourth and so on argument are the numbers from which you want to find the percentile(s).
2435              
2436             B
2437              
2438             This finds the 50-percentile (the median) to the four numbers 1, 2, 3 and 4:
2439              
2440             print "Median = " . percentile(50, 1,2,3,4); # 2.5
2441              
2442             This:
2443              
2444             @data=(11, 5, 3, 5, 7, 3, 1, 17, 4, 2, 6, 4, 12, 9, 0, 5);
2445             @p = map percentile($_,@data), (25, 50, 75);
2446              
2447             Is the same as this:
2448              
2449             @p = percentile([25, 50, 75], @data);
2450              
2451             But the latter is faster, especially if @data is large since it sorts
2452             the numbers only once internally.
2453              
2454             B
2455              
2456             Data: 1, 4, 6, 7, 8, 9, 22, 24, 39, 49, 555, 992
2457              
2458             Average (or mean) is 143
2459              
2460             Median is 15.5 (which is the average of 9 and 22 who both equally lays in the middle)
2461              
2462             The 25-percentile is 6.25 which are between 6 and 7, but closer to 6.
2463              
2464             The 75-percentile is 46.5, which are between 39 and 49 but close to 49.
2465              
2466             Linear interpolation is used to find the 25- and 75-percentile and any
2467             other x-percentile which doesn't fall exactly on one of the numbers in
2468             the set.
2469              
2470             B
2471              
2472             As you saw, 6.25 are closer to 6 than to 7 because 25% along the set of
2473             the twelve numbers is closer to the third number (6) than to he fourth
2474             (7). The median (50-percentile) is also really interpolated, but it is
2475             always in the middle of the two center numbers if there are an even count
2476             of numbers.
2477              
2478             However, there is two methods of interpolation:
2479              
2480             Example, we have only three numbers: 5, 6 and 7.
2481              
2482             Method 1: The most common is to say that 5 and 7 lays on the 25- and
2483             75-percentile. This method is used in Acme::Tools.
2484              
2485             Method 2: In Oracle databases the least and greatest numbers
2486             always lay on the 0- and 100-percentile.
2487              
2488             As an argument on why Oracles (and others?) definition is not the best way is to
2489             look at your data as for instance temperature measurements. If you
2490             place the highest temperature on the 100-percentile you are sort of
2491             saying that there can never be a higher temperatures in future measurements.
2492              
2493             A quick non-exhaustive Google survey suggests that method 1 here is most used.
2494              
2495             The larger the data sets, the less difference there is between the two methods.
2496              
2497             B
2498              
2499             In method one, when you want a percentile outside of any possible
2500             interpolation, you use the smallest and second smallest to extrapolate
2501             from. For instance in the data set C<5, 6, 7>, if you want an
2502             x-percentile of x < 25, this is below 5.
2503              
2504             If you feel tempted to go below 0 or above 100, C will
2505             I (or I to be more precise)
2506              
2507             Another method could be to use "soft curves" instead of "straight
2508             lines" in interpolation. Maybe B-splines or Bezier curves. This is not
2509             used here.
2510              
2511             For large sets of data Hoares algorithm would be faster than the
2512             simple straightforward implementation used in C
2513             here. Hoares don't sort all the numbers fully.
2514              
2515             B
2516              
2517             Data: 1, 4, 6, 7, 8, 9, 22, 24, 39, 49, 555, 992
2518              
2519             Percentile Method 1 Method 2
2520             (Acme::Tools::percentile (Oracle)
2521             and others)
2522             ----------- --------------------------- ---------
2523             0 -2 1
2524             1 -1.61 1.33
2525             25 6.25 6.75
2526             50 (median) 15.5 15.5
2527             75 46.5 41.5
2528             99 1372.19 943.93
2529             100 1429 992
2530              
2531             Found like this:
2532              
2533             perl -MAcme::Tools -le 'print for percentile([0,1,25,50,75,99,100], 1,4,6,7,8,9,22,24,39,49,555,992)'
2534              
2535             And like this in Oracle-databases:
2536              
2537             create table tmp (n number);
2538             insert into tmp values (1); insert into tmp values (4); insert into tmp values (6);
2539             insert into tmp values (7); insert into tmp values (8); insert into tmp values (9);
2540             insert into tmp values (22); insert into tmp values (24); insert into tmp values (39);
2541             insert into tmp values (49); insert into tmp values (555); insert into tmp values (992);
2542             select
2543             percentile_cont(0.00) within group(order by n) per0,
2544             percentile_cont(0.01) within group(order by n) per1,
2545             percentile_cont(0.25) within group(order by n) per25,
2546             percentile_cont(0.50) within group(order by n) per50,
2547             percentile_cont(0.75) within group(order by n) per75,
2548             percentile_cont(0.99) within group(order by n) per99,
2549             percentile_cont(1.00) within group(order by n) per100
2550             from tmp;
2551              
2552             (Oracle also provides a similar function: C where I
2553             is short for I, meaning no interpolation is taking
2554             place. Instead the closest number from the data set is picked.)
2555              
2556             =cut
2557              
2558             sub percentile {
2559 3     3 1 7 my(@p,@t,@ret);
2560 3 100       14 if(ref($_[0]) eq 'ARRAY'){ @p=@{shift()} }
  1 50       1  
  1         4  
2561 2         4 elsif(not ref($_[0])) { @p=(shift()) }
2562 0         0 else{croak()}
2563 3         7 @t=@_;
2564 3 50       9 return if !@p;
2565 3 50       8 croak if !@t;
2566 3         8 @t=sort{$a<=>$b}@t;
  72         80  
2567 3 50       9 push@t,$t[0] if @t==1;
2568 3         7 for(@p){
2569 9 50 33     40 croak if $_<0 or $_>100;
2570 9         18 my $i=(@t+1)*$_/100-1;
2571 9 50       53 push@ret,
    100          
    100          
2572             $i<0 ? $t[0]+($t[1]-$t[0])*$i:
2573             $i>$#t ? $t[-1]+($t[-1]-$t[-2])*($i-$#t):
2574             $i==int($i)? $t[$i]:
2575             $t[$i]*(int($i+1)-$i) + $t[$i+1]*($i-int($i));
2576             }
2577 3 100       56 return @p==1 ? $ret[0] : @ret;
2578             }
2579              
2580             =head1 RANDOM
2581              
2582             =head2 random
2583              
2584             B One or two arguments.
2585              
2586             B
2587              
2588             If two integer arguments: returns a random integer between the integers in argument one and two.
2589              
2590             If the first argument is an arrayref: returns a random member of that array without changing the array.
2591              
2592             If the first argument is an arrayref and there is a second arg: return that many random members of that array
2593              
2594             If the first argument is an hashref and there is no second arg: return a random key weighted by the values of that hash
2595              
2596             If the first argument is an hashref and there is a second arg: return that many random keys weighted by the values of that hash
2597              
2598             If there is no second argument and the first is an integer, a random integer between 0 and that number is returned. Including 0 and the number itself.
2599              
2600             B
2601              
2602             $dice=random(1,6); # 1, 2, 3, 4, 5 or 6
2603             $dice=random([1..6]); # same as previous
2604             @dice=random([1..6],10); # 10 dice tosses
2605             $dice=random({1=>1, 2=>1, 3=>1, 4=>1, 5=>1, 6=>2}); # weighted dice with 6 being twice as likely as the others
2606             @dice=random({1=>1, 2=>1, 3=>1, 4=>1, 5=>1, 6=>2},10); # 10 weighted dice tosses
2607             print random({head=>0.4999,tail=>0.4999,edge=>0.0002}); # coin toss (sum 1 here but not required to be)
2608             print random(2); # prints 0, 1 or 2
2609             print 2**random(7); # prints 1, 2, 4, 8, 16, 32, 64 or 128
2610             @dice=map random([1..6]), 1..10; # as third example above, but much slower
2611             perl -MAcme::Tools -le 'print for random({head=>0.499,tail=>0.499,edge=>0.002},10000);' | sort | uniq -c
2612              
2613             =cut
2614              
2615             sub random {
2616 21002     21002 1 57288 my($from,$to)=@_;
2617 21002         29728 my $ref=ref($from);
2618 21002 100       43101 if($ref eq 'ARRAY'){
    100          
2619 15001   100     74104 my @r=map $$from[rand@$from], 1..$to||1;
2620 15001 100       74889 return @_>1?@r:$r[0];
2621             }
2622             elsif($ref eq 'HASH') {
2623 4001         11371 my @k=keys%$from;
2624 28   66 28   150 my $max;do{no warnings 'uninitialized';$_>$max and $max=$_ or $_<0 and croak"negative weight" for values%$from};
  28   33     48  
  28   66     29186  
  4001         5479  
  4001         4039  
  4001         55836  
2625 4001   100     13644 my @r=map {my$r;1 while $$from{$r=$k[rand@k]}
  4010         4247  
  4010         16139  
  4010         9109  
2626 4001 100       18238 return @_>1?@r:$r[0];
2627             }
2628 2000 100       4098 ($from,$to)=(0,$from) if @_==1;
2629 2000 50       3571 ($from,$to)=($to,$from) if $from>$to;
2630 2000         6135 return int($from+rand(1+$to-$from));
2631             }
2632             #todo?: https://en.wikipedia.org/wiki/Irwin%E2%80%93Hall_distribution
2633              
2634             =head2 random_gauss
2635              
2636             Returns an pseudo-random number with a Gaussian distribution instead
2637             of the uniform distribution of perls C or C in this
2638             module. The algorithm is a variation of the one at
2639             L which is both faster
2640             and better than adding a long series of C.
2641              
2642             Uses perls C function internally.
2643              
2644             B 0 - 3 arguments.
2645              
2646             First argument: the average of the distribution. Default 0.
2647              
2648             Second argument: the standard deviation of the distribution. Default 1.
2649              
2650             Third argument: If a third argument is present, C
2651             returns an array of that many pseudo-random numbers. If there is no
2652             third argument, a number (a scalar) is returned.
2653              
2654             B One or more pseudo-random numbers with a Gaussian distribution. Also known as a Bell curve or Normal distribution.
2655              
2656             Example:
2657              
2658             my @I=random_gauss(100, 15, 100000); # produces 100000 pseudo-random numbers, average=100, stddev=15
2659             #my @I=map random_gauss(100, 15), 1..100000; # same but more than three times slower
2660             print "Average is: ".avg(@I)."\n"; # prints a number close to 100
2661             print "Stddev is: ".stddev(@I)."\n"; # prints a number close to 15
2662              
2663             my @M=grep $_>100+15*2, @I; # those above 130
2664             print "Percent above two stddevs: ".(100*@M/@I)."%\n"; #prints a number close to 2.2%
2665              
2666             Example 2:
2667              
2668             my $num=1e6;
2669             my @h; $h[$_/2]++ for random_gauss(100,15, $num);
2670             $h[$_] and printf "%3d - %3d %6d %s\n",
2671             $_*2,$_*2+1,$h[$_],'=' x ($h[$_]*1000/$num)
2672             for 1..200/2;
2673              
2674             ...prints an example of the famous Bell curve:
2675              
2676             44 - 45 70
2677             46 - 47 114
2678             48 - 49 168
2679             50 - 51 250
2680             52 - 53 395
2681             54 - 55 588
2682             56 - 57 871
2683             58 - 59 1238 =
2684             60 - 61 1807 =
2685             62 - 63 2553 ==
2686             64 - 65 3528 ===
2687             66 - 67 4797 ====
2688             68 - 69 6490 ======
2689             70 - 71 8202 ========
2690             72 - 73 10577 ==========
2691             74 - 75 13319 =============
2692             76 - 77 16283 ================
2693             78 - 79 20076 ====================
2694             80 - 81 23742 =======================
2695             82 - 83 27726 ===========================
2696             84 - 85 32205 ================================
2697             86 - 87 36577 ====================================
2698             88 - 89 40684 ========================================
2699             90 - 91 44515 ============================================
2700             92 - 93 47575 ===============================================
2701             94 - 95 50098 ==================================================
2702             96 - 97 52062 ====================================================
2703             98 - 99 53338 =====================================================
2704             100 - 101 52834 ====================================================
2705             102 - 103 52185 ====================================================
2706             104 - 105 50472 ==================================================
2707             106 - 107 47551 ===============================================
2708             108 - 109 44471 ============================================
2709             110 - 111 40704 ========================================
2710             112 - 113 36642 ====================================
2711             114 - 115 32171 ================================
2712             116 - 117 28166 ============================
2713             118 - 119 23618 =======================
2714             120 - 121 19873 ===================
2715             122 - 123 16360 ================
2716             124 - 125 13452 =============
2717             126 - 127 10575 ==========
2718             128 - 129 8283 ========
2719             130 - 131 6224 ======
2720             132 - 133 4661 ====
2721             134 - 135 3527 ===
2722             136 - 137 2516 ==
2723             138 - 139 1833 =
2724             140 - 141 1327 =
2725             142 - 143 860
2726             144 - 145 604
2727             146 - 147 428
2728             148 - 149 275
2729             150 - 151 184
2730             152 - 153 111
2731             154 - 155 67
2732              
2733             =cut
2734              
2735             sub random_gauss {
2736 1     1 1 3 my($avg,$stddev,$num)=@_;
2737 1 50       4 $avg=0 if !defined $avg;
2738 1 50       4 $stddev=1 if !defined $stddev;
2739 1 50       3 $num=1 if !defined $num;
2740 1 50       3 croak "random_gauss should not have more than 3 arguments" if @_>3;
2741 1         3 my @r;
2742 1         5 while (@r<$num) {
2743 2500         2736 my($x1,$x2,$w);
2744 2500         2636 do {
2745 3150         4271 $x1=2.0*rand()-1.0;
2746 3150         3822 $x2=2.0*rand()-1.0;
2747 3150         6852 $w=$x1*$x1+$x2*$x2;
2748             } while $w>=1.0;
2749 2500         3658 $w=sqrt(-2.0*log($w)/$w) * $stddev;
2750 2500         6100 push @r, $x1*$w + $avg,
2751             $x2*$w + $avg;
2752             }
2753 1 50       8 pop @r if @r > $num;
2754 1 50       9 return $r[0] if @_<3;
2755 1         812 return @r;
2756             }
2757              
2758             =head2 mix
2759              
2760             Mixes an array in random order. In-place if given an array reference or not if given an array.
2761              
2762             C could also have been named C, as in shuffling a deck of cards.
2763              
2764             Example:
2765              
2766             This:
2767              
2768             print mix("a".."z"),"\n" for 1..3;
2769              
2770             ...could write something like:
2771              
2772             trgoykzfqsduphlbcmxejivnwa
2773             qycatilmpgxbhrdezfwsovujkn
2774             ytogrjialbewcpvndhkxfzqsmu
2775              
2776             B
2777              
2778             =over 4
2779              
2780             =item 1.
2781             Either a reference to an array as the only input. This array will then be mixed I. The array will be changed:
2782              
2783             This: C<< @a=mix(@a) >> is the same as: C<< mix(\@a) >>.
2784              
2785             =item 2.
2786             Or an array of zero, one or more elements.
2787              
2788             =back
2789              
2790             Note that an input-array which COINCIDENTLY SOME TIMES has one element
2791             (but more other times), and that element is an array-ref, you will
2792             probably not get the expected result.
2793              
2794             To check distribution:
2795              
2796             perl -MAcme::Tools -le 'print mix("a".."z") for 1..26000'|cut -c1|sort|uniq -c|sort -n
2797              
2798             The letters a-z should occur around 1000 times each.
2799              
2800             Shuffles a deck of cards: (s=spaces, h=hearts, c=clubs, d=diamonds)
2801              
2802             perl -MAcme::Tools -le '@cards=map join("",@$_),cart([qw/s h c d/],[2..10,qw/J Q K A/]); print join " ",mix(@cards)'
2803              
2804             (Uses L, which is not a typo, see further down here)
2805              
2806             Note: C is approximately four times faster. Both respects the Perl built-in C.
2807              
2808             =cut
2809              
2810             sub mix {
2811 1020 50 33 1020 1 5191 if(@_==1 and ref($_[0]) eq 'ARRAY'){ #kun ett arg, og det er ref array
2812 0         0 my $r=$_[0];
2813 0         0 push@$r,splice(@$r,rand(@$r-$_),1) for 0..(@$r-1);
2814 0         0 return $r;
2815             }
2816             else{
2817 1020         2097 my@e=@_;
2818 1020         13494 push@e,splice(@e,rand(@e-$_),1) for 0..$#e;
2819 1020         5249 return @e;
2820             }
2821             }
2822              
2823             =head2 pwgen
2824              
2825             Generates random passwords.
2826              
2827             B 0-n args
2828              
2829             * First arg: length of password(s), default 8
2830              
2831             * Second arg: number of passwords, default 1
2832              
2833             * Third arg: string containing legal chars in password, default A-Za-z0-9,-./&%_!
2834              
2835             * Fourth to n'th arg: list of requirements for passwords, default if the third arg is false/undef (so default third arg is used) is:
2836              
2837             sub{/^[a-zA-Z0-9].*[a-zA-Z0-9]$/ and /[a-z]/ and /[A-Z]/ and /\d/ and /[,-.\/&%_!]/}
2838              
2839             ...meaning the password should:
2840             * start and end with: a letter a-z (lower- or uppercase) or a digit 0-9
2841             * should contain at least one char from each of the groups lower, upper, digit and special char
2842              
2843             To keep the default requirement-sub but add additional ones just set the fourth arg to false/undef
2844             and add your own requirements in the fifth arg and forward (examples below). Sub pwgen uses perls
2845             own C internally.
2846              
2847             C<< $Acme::Tools::Pwgen_max_sec >> and C<< $Acme::Tools::Pwgen_max_trials >> can be set to adjust for how long
2848             pwgen tries to find a password. Defaults for those are 0.01 and 10000.
2849             Whenever one of the two limits is reached, a first generates a croak.
2850              
2851             Examples:
2852              
2853             my $pw=pwgen(); # a random 8 chars password A-Z a-z 0-9 ,-./&%!_ (8 is default length)
2854             my $pw=pwgen(12); # a random 12 chars password A-Z a-z 0-9 ,-./&%!_
2855             my @pw=pwgen(0,10); # 10 random 8 chars passwords, containing the same possible chars
2856             my @pw=pwgen(0,1000,'A-Z'); # 1000 random 8 chars passwords containing just uppercase letters from A to Z
2857              
2858             pwgen(3); # dies, defaults require chars in each of 4 group (see above)
2859             pwgen(5,1,'A-C0-9', qr/^\D{3}\d{2}$/); # a 5 char string starting with three A, B or Cs and endring with two digits
2860             pwgen(5,1,'ABC0-9',sub{/^\D{3}\d{2}$/}); # same as above
2861              
2862             Examples of adding additional requirements to the default ones:
2863              
2864             my @pwreq = ( qr/^[A-C]/ );
2865             pwgen(8,1,'','',@pwreq); # use defaults for allowed chars and the standard requirements
2866             # but also demand that the password must start with A, B or C
2867              
2868             push @pwreq, sub{ not /[a-z]{3}/i };
2869             pwgen(8,1,'','',@pwreq); # as above and in addition the password should not contain three
2870             # or more consecutive letters (to avoid "offensive" words perhaps)
2871              
2872             =cut
2873              
2874             our $Pwgen_max_sec=0.01; #max seconds/password before croak (for hard to find requirements)
2875             our $Pwgen_max_trials=10000; #max trials/password before croak (for hard to find requirements)
2876             our $Pwgen_sec=0; #seconds used in last call to pwgen()
2877             our $Pwgen_trials=0; #trials in last call to pwgen()
2878 2981 100 100 2981 0 37768 sub pwgendefreq{/^[a-z\d].*[a-z\d]$/i and /[a-z]/ and /[A-Z]/ and /\d/ and /[,-.\/&%_!]/}
      100        
      100        
2879             sub pwgen {
2880 60     60 1 4560 my($len,$num,$chars,@req)=@_;
2881 60   100     134 $len||=8;
2882 60   100     126 $num||=1;
2883 60   100     137 $chars||='A-Za-z0-9,-./&%_!';
2884 60 100 50     143 $req[0]||=\&pwgendefreq if !$_[2];
2885 60         1373 $chars=~s/([$_])-([$_])/join("","$1".."$2")/eg for ('a-z','A-Z','0-9');
  125         1943  
2886 60         132 my($c,$t,@pw)=(length($chars),time_fp());
2887 60         104 ($Pwgen_trials,$Pwgen_sec)=(0,0);
2888             TRIAL:
2889 60         137 while(@pw<$num){
2890 12272 100 100     58227 croak "pwgen timeout after $Pwgen_trials trials"
2891             if ++$Pwgen_trials >= $Pwgen_max_trials
2892             or time_fp()-$t > $Pwgen_max_sec*$num;
2893 12270         77077 my $pw=join"",map substr($chars,rand($c),1),1..$len;
2894 12270         26420 for my $r (@req){
2895 18815 100       47683 if (ref($r) eq 'CODE' ){ local$_=$pw; &$r() or next TRIAL }
  7086 100       9880  
  7086 50       15387  
2896 28 100   28   156 elsif(ref($r) eq 'Regexp'){ no warnings; $pw=~$r or next TRIAL }
  28         46  
  28         7153  
  11729         56697  
2897 0         0 else { croak "pwgen: invalid req type $r ".ref($r) }
2898             }
2899 651         2566 push@pw,$pw;
2900             }
2901 58         111 $Pwgen_sec=time_fp()-$t;
2902 58 100       409 return $pw[0] if $num==1;
2903 7         352 return @pw;
2904             }
2905              
2906             # =head1 veci
2907             #
2908             # Perls C takes 1, 2, 4, 8, 16, 32 and possibly 64 as its third argument.
2909             #
2910             # This limitation is removed with C (vec improved, but much slower)
2911             #
2912             # The third argument still needs to be 32 or lower (or possibly 64 or lower).
2913             #
2914             # =cut
2915             #
2916             # sub vecibs ($) {
2917             # my($s,$o,$b,$new)=@_;
2918             # if($b=~/^(1|2|4|8|16|32|64)$/){
2919             # return vec($s,$o,$b)=$new if @_==4;
2920             # return vec($s,$o,$b);
2921             # }
2922             # my $bb=$b<4?4:$b<8?8:$b<16?16:$b<32?32:$b<64?64:die;
2923             # my $ob=int($o*$b/$bb);
2924             # my $v=vec($s,$ob,$bb)*2**$bb+vec($s,$ob+1,$bb);
2925             # $v & (2**$b-1)
2926             # }
2927              
2928              
2929             =head1 SETS
2930              
2931             =head2 distinct
2932              
2933             Returns the values of the input list, sorted alfanumerically, but only
2934             one of each value. This is the same as L except uniq does not
2935             sort the returned list.
2936              
2937             Example:
2938              
2939             print join(", ", distinct(4,9,3,4,"abc",3,"abc")); # 3, 4, 9, abc
2940             print join(", ", distinct(4,9,30,4,"abc",30,"abc")); # 30, 4, 9, abc note: alphanumeric sort
2941              
2942             =cut
2943              
2944 1     1 1 261 sub distinct { return sort keys %{{map {($_,1)} @_}} }
  1         3  
  7         22  
2945              
2946             =head2 in
2947              
2948             Returns I<1> (true) if first argument is in the list of the remaining arguments. Uses the perl-operator C<< eq >>.
2949              
2950             Otherwise it returns I<0> (false).
2951              
2952             print in( 5, 1,2,3,4,6); # 0
2953             print in( 4, 1,2,3,4,6); # 1
2954             print in( 'a', 'A','B','C','aa'); # 0
2955             print in( 'a', 'A','B','C','a'); # 1
2956              
2957             I guess in perl 5.10 or perl 6 you could use the C<< ~~ >> operator instead.
2958              
2959             =head2 in_num
2960              
2961             Just as sub L, but for numbers. Internally uses the perl operator C<< == >> instead of C< eq >.
2962              
2963             print in(5000, '5e3'); # 0
2964             print in(5000, 5e3); # 1 since 5e3 is converted to 5000 before the call
2965             print in_num(5000, 5e3); # 1
2966             print in_num(5000, '+5.0e03'); # 1
2967              
2968             =cut
2969              
2970             sub in {
2971 28     28   158 no warnings 'uninitialized';
  28         47  
  28         2630  
2972 89     89 1 125 my $val=shift;
2973 89 100       172 for(@_){ return 1 if $_ eq $val }
  282         752  
2974 6         27 return 0;
2975             }
2976              
2977             sub in_num {
2978 28     28   146 no warnings 'uninitialized';
  28         53  
  28         57939  
2979 1     1 1 2 my $val=shift;
2980 1 100       4 for(@_){ return 1 if $_ == $val }
  5000         8972  
2981 0         0 return 0;
2982             }
2983              
2984             =head2 union
2985              
2986             Input: Two arrayrefs. (Two lists, that is)
2987              
2988             Output: An array containing all elements from both input lists, but no element more than once even if it occurs twice or more in the input.
2989              
2990             Example, prints 1,2,3,4:
2991              
2992             perl -MAcme::Tools -le 'print join ",", union([1,2,3],[2,3,3,4,4])' # 1,2,3,4
2993              
2994             =cut
2995              
2996 1     1 1 2 sub union { my %seen; grep !$seen{$_}++, map @{shift()},@_ }
  1         3  
  2         14  
2997             =head2 minus
2998              
2999             Input: Two arrayrefs.
3000              
3001             Output: An array containing all elements in the first input array but not in the second.
3002              
3003             Example:
3004              
3005             perl -MAcme::Tools -le 'print join " ", minus( ["five", "FIVE", 1, 2, 3.0, 4], [4, 3, "FIVE"] )'
3006              
3007             Output is C<< five 1 2 >>.
3008              
3009             =cut
3010              
3011             sub minus {
3012 1     1 0 2 my %seen;
3013 1         2 my %notme=map{($_=>1)}@{$_[1]};
  3         8  
  1         2  
3014 1   66     3 grep !$notme{$_}&&!$seen{$_}++, @{$_[0]};
  1         35  
3015             }
3016              
3017             =head2 intersect
3018              
3019             Input: Two arrayrefs
3020              
3021             Output: An array containing all elements which exists in both input arrays.
3022              
3023             Example:
3024              
3025             perl -MAcme::Tools -le 'print join" ", intersect( ["five", 1, 2, 3.0, 4], [4, 2+1, "five"] )' # 4 3 five
3026              
3027             Output: C<< 4 3 five >>
3028              
3029             =cut
3030              
3031             sub intersect {
3032 42     42 1 48 my %first=map{($_=>1)}@{$_[0]};
  50         140  
  42         72  
3033 42         60 my %seen;
3034 42 100       44 return grep{$first{$_}&&!$seen{$_}++}@{$_[1]};
  48         299  
  42         75  
3035             }
3036              
3037             =head2 not_intersect
3038              
3039             Input: Two arrayrefs
3040              
3041             Output: An array containing all elements member of just one of the input arrays (not both).
3042              
3043             Example:
3044              
3045             perl -MAcme::Tools -le ' print join " ", not_intersect( ["five", 1, 2, 3.0, 4], [4, 2+1, "five"] )'
3046              
3047             The output is C<< 1 2 >>.
3048              
3049             =cut
3050              
3051             sub not_intersect {
3052 1     1 1 10 my %code;
3053             my %seen;
3054 1         3 for(@{$_[0]}){$code{$_}|=1}
  1         4  
  5         14  
3055 1         2 for(@{$_[1]}){$code{$_}|=2}
  1         4  
  3         6  
3056 1 100       2 return grep{$code{$_}!=3&&!$seen{$_}++}(@{$_[0]},@{$_[1]});
  8         35  
  1         3  
  1         2  
3057             }
3058              
3059             =head2 uniq
3060              
3061             Input: An array of strings (or numbers)
3062              
3063             Output: The same array in the same order, except elements which exists earlier in the list.
3064              
3065             Same as L but distinct sorts the returned list, I does not.
3066              
3067             Example:
3068              
3069             my @t=(7,2,3,3,4,2,1,4,5,3,"x","xx","x",02,"07");
3070             print join " ", uniq @t; # prints 7 2 3 4 1 5 x xx 07
3071              
3072             =cut
3073              
3074 1     1 1 2 sub uniq(@) { my %seen; grep !$seen{$_}++, @_ }
  1         24  
3075              
3076             =head1 HASHES
3077              
3078             =head2 subhash
3079              
3080             Copies a subset of keys/values from one hash to another.
3081              
3082             B First argument is a reference to a hash. The rest of the arguments are a list of the keys of which key/value-pair you want to be copied.
3083              
3084             B The hash consisting of the keys and values you specified.
3085              
3086             Example:
3087              
3088             %population = ( Norway=>5000000, Sweden=>9500000, Finland=>5400000,
3089             Denmark=>5600000, Iceland=>320000,
3090             India => 1.21e9, China=>1.35e9, USA=>313e6, UK=>62e6 );
3091              
3092             %scandinavia = subhash( \%population , 'Norway', 'Sweden', 'Denmark' ); # this and
3093             %scandinavia = (Norway=>5000000,Sweden=>9500000,Denmark=>5600000); # this is the same
3094              
3095             print "Population of $_ is $scandinavia{$_}\n" for keys %scandinavia;
3096              
3097             ...prints the populations of the three scandinavian countries.
3098              
3099             Note: The values are NOT deep copied when they are references. (Use C<< Storable::dclone() >> to do that).
3100              
3101             Note2: For perl version 5.20+ subhashes (hash slices returning keys as well as values) is built in like this:
3102              
3103             %scandinavia = %population{'Norway','Sweden','Denmark'};
3104              
3105             =cut
3106              
3107             sub subhash {
3108 1     1 1 3 my $hr=shift;
3109 1         1 my @r;
3110 1         3 for(@_){ push@r,($_=>$$hr{$_}) }
  3         9  
3111 1         10 return @r;
3112             }
3113              
3114             =head2 hashtrans
3115              
3116             B a reference to a hash of hashes
3117              
3118             B a hash like the input-hash, but matrix transposed (kind of). Think of it as if X and Y has swapped places.
3119              
3120             %h = ( 1 => {a=>33,b=>55},
3121             2 => {a=>11,b=>22},
3122             3 => {a=>88,b=>99} );
3123             print serialize({hashtrans(\%h)},'v');
3124              
3125             Gives:
3126              
3127             %v=( 'a'=>{'1'=>'33','2'=>'11','3'=>'88'},
3128             'b'=>{'1'=>'55','2'=>'22','3'=>'99'} );
3129              
3130             =cut
3131              
3132             #Hashtrans brukes automatisk når første argument er -1 i sub hashtabell()
3133              
3134             sub hashtrans {
3135 1     1 1 2 my $h=shift;
3136 1         2 my %new;
3137 1         4 for my $k (keys%$h){
3138 3         4 my $r=$$h{$k};
3139 3         14 for(keys%$r){
3140 6         15 $new{$_}{$k}=$$r{$_};
3141             }
3142             }
3143 1         11 return %new;
3144             }
3145              
3146             =head1 COMPRESSION
3147              
3148             L, L, L, L, L, and L
3149             compresses and uncompresses strings to save space in disk, memory,
3150             database or network transfer. Trades time for space. (Beware of wormholes)
3151              
3152             =head2 zipb64
3153              
3154             Compresses the input (text or binary) and returns a base64-encoded string of the compressed binary data.
3155             No known limit on input length, several MB has been tested, as long as you've got the RAM...
3156              
3157             B One or two strings.
3158              
3159             First argument: The string to be compressed.
3160              
3161             Second argument is optional: A I string.
3162              
3163             B a base64-kodet string of the compressed input.
3164              
3165             The use of an optional I string will result in an even
3166             further compressed output in the dictionary string is somewhat similar
3167             to the string that is compressed (the data in the first argument).
3168              
3169             If x relatively similar string are to be compressed, i.e. x number
3170             automatic of email responses to some action by a user, it will pay of
3171             to choose one of those x as a dictionary string and store it as
3172             such. (You will also use the same dictionary string when decompressing
3173             using L.
3174              
3175             The returned string is base64 encoded. That is, the output is 33%
3176             larger than it has to be. The advantage is that this string more
3177             easily can be stored in a database (without the hassles of CLOB/BLOB)
3178             or perhaps easier transfer in http POST requests (it still needs some
3179             url-encoding, normally). See L and L for the
3180             same without base 64 encoding.
3181              
3182             Example 1, normal compression without dictionary:
3183              
3184             $txt = "Test av komprimering, hva skjer? " x 10; # ten copies of this norwegian string, $txt is now 330 bytes (or chars rather...)
3185             print length($txt)," bytes input!\n"; # prints 330
3186             $zip = zipb64($txt); # compresses
3187             print length($zip)," bytes output!\n"; # prints 65
3188             print $zip; # prints the base64 string ("noise")
3189              
3190             $output=unzipb64($zip); # decompresses
3191             print "Hurra\n" if $output eq $txt; # prints Hurra if everything went well
3192             print length($output),"\n"; # prints 330
3193              
3194             Example 2, same compression, now with dictionary:
3195              
3196             $txt = "Test av komprimering, hva skjer? " x 10; # Same original string as above
3197             $dict = "Testing av kompresjon, hva vil skje?"; # dictionary with certain similarities
3198             # of the text to be compressed
3199             $zip2 = zipb64($txt,$dict); # compressing with $dict as dictionary
3200             print length($zip2)," bytes output!\n"; # prints 49, which is less than 65 in ex. 1 above
3201             $output=unzipb64($zip2,$dict); # uses $dict in the decompressions too
3202             print "Hurra\n" if $output eq $txt; # prints Hurra if everything went well
3203              
3204              
3205             Example 3, dictionary = string to be compressed: (out of curiosity)
3206              
3207             $txt = "Test av komprimering, hva skjer? " x 10; # Same original string as above
3208             $zip3 = zipb64($txt,$txt); # hmm
3209             print length($zip3)," bytes output!\n"; # prints 25
3210             print "Hurra\n" if unzipb64($zip3,$txt) eq $txt; # hipp hipp ...
3211              
3212             zipb64() and zipbin() is really just wrappers around L and C & co there.
3213              
3214             =cut
3215              
3216             sub zipb64 {
3217 9     9 1 996 require MIME::Base64;
3218 9         21728 return MIME::Base64::encode_base64(zipbin(@_));
3219             }
3220              
3221              
3222             =head2 zipbin
3223              
3224             C does the same as C except that zipbin()
3225             does not base64 encode the result. Returns binary data.
3226              
3227             See L for documentation.
3228              
3229             =cut
3230              
3231             sub zipbin {
3232 17     17 1 125 require Compress::Zlib;
3233 17         39 my($data,$dict)=@_;
3234 17 50 100     166 my $x=Compress::Zlib::deflateInit(-Dictionary=>$dict||'',-Level=>Compress::Zlib::Z_BEST_COMPRESSION()) or croak();
3235 17 50       7977 my($output,$status)=$x->deflate($data); croak() if $status!=Compress::Zlib::Z_OK();
  17         84501  
3236 17 50       131 my($out,$status2)=$x->flush(); croak() if $status2!=Compress::Zlib::Z_OK();
  17         3057  
3237 17         779 return $output.$out;
3238             }
3239              
3240             =head2 unzipb64
3241              
3242             Opposite of L.
3243              
3244             Input:
3245              
3246             First argument: A string made by L
3247              
3248             Second argument: (optional) a dictionary string which where used in L.
3249              
3250             Output: The original string (be it text or binary).
3251              
3252             See L.
3253              
3254             =cut
3255              
3256             sub unzipb64 {
3257 2     2 1 7 my($data,$dict)=@_;
3258 2         15 require MIME::Base64;
3259 2         52 unzipbin(MIME::Base64::decode_base64($data),$dict);
3260             }
3261              
3262             =head2 unzipbin
3263              
3264             C does the same as L except that C
3265             wants a pure binary compressed string as input, not base64.
3266              
3267             See L for documentation.
3268              
3269             =cut
3270              
3271             sub unzipbin {
3272 5     5 1 22 require Compress::Zlib;
3273 5         23 require Carp;
3274 5         12 my($data,$dict)=@_;
3275 5 50 50     43 my $x=Compress::Zlib::inflateInit(-Dictionary=>$dict||'') or croak();
3276 5         748 my($output,$status)=$x->inflate($data);
3277 5 50       738 croak() if $status!=Compress::Zlib::Z_STREAM_END();
3278 5         155 return $output;
3279             }
3280              
3281             =head2 gzip
3282              
3283             B A string you want to compress. Text or binary.
3284              
3285             B The binary compressed representation of that input string.
3286              
3287             C is really the same as C< Compress:Zlib::memGzip() > except
3288             that C just returns the input-string if for some reason L
3289             could not be C. Not installed or not found. (L is a built in module in newer perl versions).
3290              
3291             C uses the same compression algorithm as the well known GNU program gzip found in most unix/linux/cygwin distros. Except C does this in-memory. (Both using the C-library C).
3292              
3293             =cut
3294              
3295             sub gzip {
3296 8     8 1 622 my $s=shift();
3297 8         20 eval{ # tries gzip, if it works it works, else returns the input
3298 8         2211 require Compress::Zlib;
3299 8         136008 $s=Compress::Zlib::memGzip(\$s);
3300 8         72025 };undef$@;
3301 8         85 return $s;
3302             }
3303              
3304             =head2 gunzip
3305              
3306             B A binary compressed string. I.e. something returned from
3307             C earlier or read from a C<< .gz >> file.
3308              
3309             B The original larger non-compressed string. Text or binary.
3310              
3311             =cut
3312              
3313             sub gunzip {
3314 3     3 1 8 my $s=shift();
3315 3         6 eval {
3316 3         16 require Compress::Zlib;
3317 3         12 $s=Compress::Zlib::memGunzip(\$s);
3318 3         891 };undef$@;
3319 3         18 return $s;
3320             }
3321              
3322             =head2 bzip2
3323              
3324             See L and L.
3325              
3326             C and C works just as C and C,
3327             but use another compression algorithm. This is usually better but slower
3328             than the C-algorithm. Especially in the compression. Decompression speed is less different.
3329              
3330             See also C, C and L
3331              
3332             =cut
3333              
3334             sub bzip2 {
3335 0     0 1 0 my $s=shift();
3336 0         0 eval { require Compress::Bzip2; $s=Compress::Bzip2::memBzip($s) }; undef$@;
  0         0  
  0         0  
  0         0  
3337 0         0 return $s;
3338             }
3339              
3340             =head2 bunzip2
3341              
3342             Decompressed something compressed by bzip2() or the data from a C<.bz2> file. See L.
3343              
3344             =cut
3345              
3346             sub bunzip2 {
3347 0     0 1 0 my $s=shift();
3348 0         0 eval { require Compress::Bzip2; $s=Compress::Bzip2::memBunzip($s) }; undef$@;
  0         0  
  0         0  
  0         0  
3349 0         0 return $s;
3350             }
3351              
3352              
3353             =head1 NET, WEB, CGI-STUFF
3354              
3355             =head2 ipaddr
3356              
3357             B an IP-number
3358              
3359             B either an IP-address I or an empty string
3360             if the DNS lookup didn't find anything.
3361              
3362             Example:
3363              
3364             perl -MAcme::Tools -le 'print ipaddr("129.240.8.200")' # prints www.uio.no
3365              
3366             Uses perls C internally.
3367              
3368             C memoizes the results internally (using the
3369             C<%Acme::Tools::IPADDR_memo> hash) so only the first loopup on a
3370             particular IP number might take some time.
3371              
3372             Some few DNS loopups can take several seconds.
3373             Most is done in a fraction of a second. Due to this slowness, medium to high traffic web servers should
3374             probably turn off hostname lookups in their logs and just log IP numbers by using
3375             C in Apache C and then use I afterwards if necessary.
3376              
3377             =cut
3378              
3379             our %IPADDR_memo;
3380             sub ipaddr {
3381 2     2 1 506 my $ipnr=shift;
3382             #NB, 2-tallet på neste kodelinje er ikke det samme på alle os,
3383             #men ser ut til å funke i linux og hpux. Den Riktige Måten(tm)
3384             #er konstanten AF_INET i Socket eller IO::Socket-pakken.
3385 2   66     176520 return $IPADDR_memo{$ipnr} ||= gethostbyaddr(pack("C4",split("\\.",$ipnr)),2);
3386             }
3387              
3388             =head2 ipnum
3389              
3390             C does the opposite of C
3391              
3392             Does an attempt of converting an IP address (hostname) to an IP number.
3393             Uses DNS name servers via perls internal C.
3394             Return empty string (undef) if unsuccessful.
3395              
3396             print ipnum("www.uio.no"); # prints 129.240.13.152
3397              
3398             Does internal memoization via the hash C<%Acme::Tools::IPNUM_memo>.
3399              
3400             =cut
3401              
3402             our %IPNUM_memo;
3403             sub ipnum {
3404 1     1 1 3 my $ipaddr=shift;
3405             #croak "No $ipaddr" if !length($ipaddr);
3406 1 50       4 return $IPNUM_memo{$ipaddr} if exists $IPNUM_memo{$ipaddr};
3407 1         48973 my $h=gethostbyname($ipaddr);
3408             #croak "No ipnum for $ipaddr" if !$h;
3409 1 50       16 return if !defined $h;
3410 1         24 my $ipnum = join(".",unpack("C4",$h));
3411 1 50       33 $IPNUM_memo{$ipaddr} = $ipnum=~/^(\d+\.){3}\d+$/ ? $ipnum : undef;
3412 1         11 return $IPNUM_memo{$ipaddr};
3413             }
3414              
3415             =head2 webparams
3416              
3417             B (optional)
3418              
3419             Zero or one input argument: A string of the same type often found behind the first question mark (C<< ? >>) in URLs.
3420              
3421             This string can have one or more parts separated by C<&> chars.
3422              
3423             Each part consists of C pairs (with the first C<=> char being the separation char).
3424              
3425             Both C and C can be url-encoded.
3426              
3427             If there is no input argument, C uses C<< $ENV{QUERY_STRING} >> instead.
3428              
3429             If also C<< $ENV{QUERY_STRING} >> is lacking, C checks if C<< $ENV{REQUEST_METHOD} eq 'POST' >>.
3430             In that case C<< $ENV{CONTENT_LENGTH} >> is taken as the number of bytes to be read from C
3431             and those bytes are used as the missing input argument.
3432              
3433             The environment variables QUERY_STRING, REQUEST_METHOD and CONTENT_LENGTH is
3434             typically set by a web server following the CGI standard (which Apache and
3435             most of them can do I guess) or in mod_perl by Apache. Although you are
3436             probably better off using L. Or C<< $R->args() >> or C<< $R->content() >> in mod_perl.
3437              
3438             B
3439              
3440             C returns a hash of the key/value pairs in the input argument. Url-decoded.
3441              
3442             If an input string has more than one occurrence of the same key, that keys value in the returned hash will become concatenated each value separated by a C<,> char. (A comma char)
3443              
3444             Examples:
3445              
3446             use Acme::Tools;
3447             my %R=webparams();
3448             print "Content-Type: text/plain\n\n"; # or rather \cM\cJ\cM\cJ instead of \n\n to be http-compliant
3449             print "My name is $R{name}";
3450              
3451             Storing those four lines in a file in the directory designated for CGI-scripts
3452             on your web server (or perhaps naming the file .cgi is enough), and C
3453             /.../cgi-bin/script> and the URL
3454             L will print
3455             C to the web page.
3456              
3457             L will print C.
3458              
3459             =cut
3460              
3461             sub webparams {
3462 2     2 1 394 my $query=shift();
3463 2 50       9 $query=$ENV{QUERY_STRING} if !defined $query;
3464 2 50 33     7 if(!defined $query and $ENV{REQUEST_METHOD} eq "POST"){
3465 0         0 read(STDIN,$query , $ENV{CONTENT_LENGTH});
3466 0         0 $ENV{QUERY_STRING}=$query;
3467             }
3468 2         3 my %R;
3469 2         15 for(split("&",$query)){
3470 7 50       18 next if !length($_);
3471 7         22 my($nkl,$verdi)=map urldec($_),split("=",$_,2);
3472 7 100       30 $R{$nkl}=exists$R{$nkl}?"$R{$nkl},$verdi":$verdi;
3473             }
3474 2         15 return %R;
3475             }
3476              
3477             =head2 urlenc
3478              
3479             Input: a string
3480              
3481             Output: the same string URL encoded so it can be sent in URLs or POST requests.
3482              
3483             In URLs (web addresses) certain characters are illegal. For instance I and I.
3484             And certain other chars have special meaning, such as C<+>, C<%>, C<=>, C, C<&>.
3485              
3486             These illegal and special chars needs to be encoded to be sent in
3487             URLs. This is done by sending them as C<%> and two hex-digits. All
3488             chars can be URL encodes this way, but it's necessary just on some.
3489              
3490             Example:
3491              
3492             $search="Østdal, Åge";
3493             my $url="http://machine.somewhere.com/search?q=" . urlenc($search);
3494             print $url;
3495              
3496             Prints C<< http://machine.somewhere.com/search?q=%D8stdal%2C%20%C5ge >>
3497              
3498             =cut
3499              
3500             sub urlenc {
3501 4     4 1 20 my $str=shift;
3502 4         16 $str=~s/([^\w\-\.\/\,\[\]])/sprintf("%%%02x",ord($1))/eg; #more chars is probably legal...
  608         1569  
3503 4         26 return $str;
3504             }
3505              
3506             =head2 urldec
3507              
3508             Opposite of L.
3509              
3510             Example, this returns 'C< ø>'. That is space and C<< ø >>.
3511              
3512             urldec('+%C3')
3513              
3514             =cut
3515              
3516             sub urldec {
3517 14     14 1 18 my $str=shift;
3518 14         107 $str=~s/\+/ /gs;
3519 14         25 $str=~s/%([a-f\d]{2})/pack("C", hex($1))/egi;
  609         1520  
3520 14         61 return $str;
3521             }
3522              
3523             =head2 ht2t
3524              
3525             C is short for I.
3526              
3527             This sub extracts an html-C<< >>s and returns its C<< s >>
3528             and C<< s >> as an array of arrayrefs. And strips away any html
3529             inside the C<< s >> as well.
3530              
3531             my @table = ht2t($html,'some string occuring before the you want');
3532              
3533             Input: One or two arguments.
3534              
3535             First argument: the html where a C<< >> is to be found and converted.
3536              
3537             Second argument: (optional) If the html contains more than one C<<
3538             >>, and you do not want the first one, applying a second
3539             argument is a way of telling C which to capture: the one with this word
3540             or string occurring before it.
3541              
3542             Output: An array of arrayrefs.
3543              
3544             C is a quick and dirty way of scraping (or harvesting as it is
3545             also called) data from a web page. Look too L to do this
3546             more accurate.
3547              
3548             Example:
3549              
3550             use Acme::Tools;
3551             use LWP::Simple;
3552             my $url = "http://en.wikipedia.org/wiki/List_of_countries_by_population";
3553             for( ht2t( get($url), "Countries" ) ) {
3554             my($rank, $country, $pop) = @$_;
3555             $pop =~ s/,//g;
3556             printf "%3d | %-32s | %9d\n", @$_ if $pop>0;
3557             }
3558              
3559             Output:
3560              
3561             1 | China | 1367740000
3562             2 | India | 1262090000
3563             3 | United States | 319043000
3564             4 | Indonesia | 252164800
3565             5 | Brazil | 203404000
3566              
3567             ...and so on.
3568              
3569             =cut
3570              
3571             sub ht2t {
3572 9 100 100 9 1 451 my($f,$s,$r)=@_; 1>@_||@_>3 and croak; $s='' if @_==1;
  9 100       314  
  7         17  
3573 7         121 $f=~s,.*?($s).*?(
3574 28     28   835971 my $e=0;$e++ while index($f,$s=chr($e))>=$[;
  28         13345  
  28         104398  
  7         13  
  7         36  
3575 7         85 $f=~s//\l$1$s/gsi;
3576 7         54 $f=~s/\s*<.*?>\s*/ /gsi;
3577 7         66 my @t=split("r$s",$f);shift @t;
  7         12  
3578 20     20   32 $r||=sub{s/&(#160|nbsp);/ /g;s/&/&/g;s/^\s*(.*?)\s*$/$1/s;
  20         28  
  20         81  
3579 7 100 100     38 s/(\d) (\d)/$1$2/g if /^[\d \.\,]+$/};
  20         71  
3580 7         16 for(@t){my @r=split/[dh]$s/;shift@r;$_=[map{&$r;$_}@r]}
  9         52  
  9         14  
  9         16  
  20         31  
  20         64  
3581 7         38 @t;
3582             }
3583              
3584             =head1 FILES, DIRECTORIES
3585              
3586             =head2 writefile
3587              
3588             Justification:
3589              
3590             Perl needs three or four operations to make a file out of a string:
3591              
3592             open my $FILE, '>', $filename or die $!;
3593             print $FILE $text;
3594             close($FILE);
3595              
3596             This is way simpler:
3597              
3598             writefile($filename,$text);
3599              
3600             Sub writefile opens the file i binary mode (C) and has two usage modes:
3601              
3602             B Two arguments
3603              
3604             B is the filename. If the file exists, its overwritten.
3605             If the file can not be opened for writing, a die (a croak really) happens.
3606              
3607             B is one of:
3608              
3609             =over 4
3610              
3611             =item * Either a scaler. That is a normal string to be written to the file.
3612              
3613             =item * Or a reference to a scalar. That referred text is written to the file.
3614              
3615             =item * Or a reference to an array of scalars. This array is the written to the
3616             file element by element and C<< \n >> is automatically appended to each element.
3617              
3618             =back
3619              
3620             Alternativelly, you can write several files at once.
3621              
3622             Example, this:
3623              
3624             writefile('file1.txt','The text....tjo');
3625             writefile('file2.txt','The text....hip');
3626             writefile('file3.txt','The text....and hop');
3627              
3628             ...is the same as this:
3629              
3630             writefile([
3631             ['file1.txt','The text....tjo'],
3632             ['file2.txt','The text....hip'],
3633             ['file3.txt','The text....and hop'],
3634             ]);
3635              
3636             B Nothing (for the time being). Cs (C really) if something goes wrong.
3637              
3638             =cut
3639              
3640             #todo: use openstr() as in readfile(), transparently gzip .gz filenames and so on
3641             sub writefile {
3642 4     4 1 70151 my($filename,$text)=@_;
3643 4 50       25 if(ref($filename) eq 'ARRAY'){
3644 0         0 writefile(@$_) for @$filename;
3645 0         0 return;
3646             }
3647 4 50 33     306 open(WRITEFILE,">",$filename) and binmode(WRITEFILE) or croak($!);
3648 4 50 33     41 if(!defined $text or !ref($text)){
    0          
    0          
3649 4         733 print WRITEFILE $text;
3650             }
3651             elsif(ref($text) eq 'SCALAR'){
3652 0         0 print WRITEFILE $$text;
3653             }
3654             elsif(ref($text) eq 'ARRAY'){
3655 0         0 print WRITEFILE "$_\n" for @$text;
3656             }
3657             else {
3658 0         0 croak;
3659             }
3660 4         167 close(WRITEFILE);
3661 4         15 return;
3662             }
3663              
3664             =head2 readfile
3665              
3666             Just as with L you can read in a whole file in one operation with C. Instead of:
3667              
3668             open my $FILE,'<', $filename or die $!;
3669             my $data = join"",<$FILE>;
3670             close($FILE);
3671              
3672             This is simpler:
3673              
3674             my $data = readfile($filename);
3675              
3676             B
3677              
3678             Reading the content of the file to a scalar variable: (Any content in C<$data> will be overwritten)
3679              
3680             my $data;
3681             readfile('filename.txt',\$data);
3682              
3683             Reading the lines of a file into an array:
3684              
3685             my @lines;
3686             readfile('filnavn.txt',\@lines);
3687             for(@lines){
3688             ...
3689             }
3690              
3691             Note: Chomp is done on each line. That is, any newlines (C<< \n >>) will be removed.
3692             If C<@lines> is non-empty, this will be lost.
3693              
3694             Sub readfile is context aware. If an array is expected it returns an array of the lines without a trailing C<< \n >>.
3695             The last example can be rewritten:
3696              
3697             for(readfile('filnavn.txt')){
3698             ...
3699             }
3700              
3701             With two input arguments, nothing (undef) is returned from C.
3702              
3703             =cut
3704              
3705             #http://blogs.perl.org/users/leon_timmermans/2013/05/why-you-dont-need-fileslurp.html
3706             #todo: readfile with grep-filter code ref in a third arg (avoid reading all into mem)
3707              
3708             sub readfile {
3709 12     12 1 11518 my($filename,$ref)=@_;
3710 12 100       59 if(@_==1){
3711 6 100       22 if(wantarray){ my @data; readfile($filename,\@data); return @data }
  1         3  
  1         5  
  1         4976  
3712 5         8 else { my $data; readfile($filename,\$data); return $data }
  5         457  
  5         698  
3713             }
3714             else {
3715 6 50       46 open my $fh,openstr($filename) or croak("ERROR: readfile $! $?");
3716 6 100       30 if ( ref($ref) eq 'SCALAR') { $$ref=join"",<$fh> }
  5 50       6899  
3717 1         18 elsif( ref($ref) eq 'ARRAY' ) { while(my $l=<$fh>){ chomp($l); push @$ref, $l } }
  20003         20569  
  20003         54199  
3718 0         0 else { croak "ERROR: Second arg to readfile should be a ref to a scalar og array" }
3719 6         1166 close($fh);
3720 6         38 return;#?
3721             }
3722             }
3723              
3724             =head2 readdirectory
3725              
3726             B
3727              
3728             Name of a directory.
3729              
3730             B
3731              
3732             A list of all files in it, except of C<.> and C<..> (on linux/unix systems, all directories have a C<.> and C<..> directory).
3733              
3734             The names of all types of files are returned: normal files, directories, symbolic links,
3735             pipes, semaphores. That is every thing shown by C except C<.> and C<..>
3736              
3737             C do not recurce down into subdirectories (but see example below).
3738              
3739             B
3740              
3741             my @files = readdirectory("/tmp");
3742              
3743             B
3744              
3745             Sometimes calling the built ins C, C and C seems a tad tedious, since this:
3746              
3747             my $dir="/usr/bin";
3748             opendir(D,$dir);
3749             my @files=map "$dir/$_", grep {!/^\.\.?$/} readdir(D);
3750             closedir(D);
3751              
3752             Is the same as this:
3753              
3754             my @files=readdirectory("/usr/bin");
3755              
3756             See also: L
3757              
3758             B
3759              
3760             On huge directories with perhaps tens or houndreds of thousands of
3761             files, readdirectory() will consume more memory than perls
3762             opendir/readdir. This isn't usually a concern anymore for modern
3763             computers with gigabytes of RAM, but might be the rationale behind
3764             Perls more tedious way created in the 80s. The same argument goes for
3765             file slurping. On the other side it's also a good practice to never
3766             assume to much on available memory and the number of files if you
3767             don't know for certain that enough memory is available whereever your
3768             code is run or that the size of the directory is limited.
3769              
3770             B
3771              
3772             How to get all files in the C directory including all subdirectories below of any depth:
3773              
3774             my @files=("/tmp");
3775             map {-d $_ and unshift @files,$_ or push @files,$_} readdirectory(shift(@files)) while -d $files[0];
3776              
3777             ...or to avoid symlinks and only get real files:
3778              
3779             map {-d and !-l and unshift @files,$_ or -f and !-l and push @files,$_} readdirectory(shift(@files)) while -d $files[0];
3780              
3781             =cut
3782              
3783             sub readdirectory {
3784 0     0 1 0 my $dir=shift;
3785 0         0 opendir(my $D,$dir);
3786 0         0 my @filer=map "$dir/$_", grep {!/^\.\.?$/} readdir($D);
  0         0  
3787 0         0 closedir($D);
3788 0         0 return @filer;
3789             }
3790              
3791             =head2 basename
3792              
3793             The basename and dirname functions behaves like the *nix shell commands with the same names.
3794              
3795             B One or two arguments: Filename and an optional suffix
3796              
3797             B Returns the filename with any directory and (if given) the suffix removed.
3798              
3799             basename('/usr/bin/perl') # returns 'perl'
3800             basename('/usr/local/bin/report.pl','.pl') # returns 'report' since .pl at the end is removed
3801             basename('report2.pl','.pl') # returns 'report2'
3802             basename('report2.pl','.\w+') # returns 'report2.pl', probably not what you meant
3803             basename('report2.pl',qr/.\w+/) # returns 'report2', use qr for regex
3804              
3805             =head2 dirname
3806              
3807             B A filename including path
3808              
3809             B Removes the filename path and returns just the directory path up until but not including
3810             the last /. Return just a one char C<< . >> (period string) if there is no directory in the input.
3811              
3812             dirname('/usr/bin/perl') # returns '/usr/bin'
3813             dirname('perl') # returns '.'
3814              
3815             =head2 username
3816              
3817             Returns the current linux/unix username, for example the string root
3818              
3819             print username(); #just (getpwuid($<))[0] but more readable perhaps
3820              
3821             =cut
3822              
3823 8 100   8 1 3286 sub basename { my($f,$s)=(@_,'');$s=quotemeta($s)if!ref($s);$f=~m,^(.*/)?([^/]*?)($s)?$,;$2 }
  8         25  
  8         226  
  8         38  
3824 2 100 66 2 1 438 sub dirname { $_[0]=~m,^(.*)/,;defined($1) && length($1) ? $1 : '.' }
  2         23  
3825 0     0 1 0 sub username { (getpwuid($<))[0] }
3826              
3827             =head2 wipe
3828              
3829             Deletes a file by "wiping" it on the disk. Overwrites the file before deleting. (May not work properly on SSDs)
3830              
3831             B
3832             * Arg 1: A filename
3833             * Optional arg 2: number of times to overwrite file. Default is 3 if omitted, 0 or undef
3834             * Optional arg 3: keep (true/false), wipe() but no delete of file
3835              
3836             B Same as the C (remove file): 1 for success, 0 or false for failure.
3837              
3838             See also: L, L
3839              
3840             =cut
3841              
3842             sub wipe {
3843 2     2 1 704 my($file,$times,$keep)=@_;
3844 2   100     14 $times||=3;
3845 2 50 33     82 croak "ERROR: File $file nonexisting\n" if not -f $file or not -e $file;
3846 2         28 my $size=-s$file;
3847 2 50       78 open my $WIFH, '+<', $file or croak "ERROR: Unable to open $file: $!\n";
3848 2         5 binmode($WIFH);
3849 2         8 for(1..$times){
3850 4         16 my $block=chr(int(rand(256))) x 1024;#hm
3851 4         10 for(0..($size/1024)){
3852 73         521 seek($WIFH,$_*1024,0);
3853 73         142 print $WIFH $block;
3854             }
3855             }
3856 2         30 close($WIFH);
3857 2 100       141 $keep || unlink($file);
3858             }
3859              
3860             =head2 chall
3861              
3862             Does chmod + utime + chown on one or more files.
3863              
3864             Returns the number of files of which those operations was successful.
3865              
3866             Mode, uid, gid, atime and mtime are set from the array ref in the first argument.
3867              
3868             The first argument references an array which is exactly like an array returned from perls internal C -function.
3869              
3870             Example:
3871              
3872             my @stat=stat($filenameA);
3873             chall( \@stat, $filenameB, $filenameC, ... ); # by stat-array
3874             chall( $filenameA, $filenameB, $filenameC, ... ); # by file name
3875              
3876             Copies the chmod, owner, group, access time and modify time from file A to file B and C.
3877              
3878             See C, C, C, C
3879              
3880             =cut
3881              
3882              
3883             sub chall {
3884             my($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks )
3885 1 50   1 1 28244 = ref($_[0]) ? @{shift()} : stat(shift());
  1         4  
3886 1         2 my $successful=0;
3887 1 50 33     4 for(@_){ chmod($mode,$_) && utime($atime,$mtime,$_) && chown($uid,$gid,$_) && $successful++ }
  1   33     73  
3888 1         3 return $successful;
3889             }
3890              
3891             =head2 makedir
3892              
3893             Input: One or two arguments.
3894              
3895             Works like perls C except that C will create nesessary parent directories if they dont exists.
3896              
3897             First input argument: A directory name (absolute, starting with C< / > or relative).
3898              
3899             Second input argument: (optional) permission bits. Using the normal C<< 0777^umask() >> as the default if no second input argument is provided.
3900              
3901             Example:
3902              
3903             makedir("dirB/dirC")
3904              
3905             ...will create directory C if it does not already exists, to be able to create C inside C.
3906              
3907             Returns true on success, otherwise false.
3908              
3909             C memoizes directories it has checked for existence before (trading memory and for speed).
3910             Thus directories removed during running the script is not discovered by makedir.
3911              
3912             See also C<< perldoc -f mkdir >>, C<< man umask >>
3913              
3914             =cut
3915              
3916             our %MAKEDIR;
3917              
3918             sub makedir {
3919 0     0 1 0 my($d,$p,$dd)=@_;
3920 0 0       0 $p=0777^umask() if !defined$p;
3921             (
3922             $MAKEDIR{$d} or -d$d or mkdir($d,$p) #or croak("mkdir $d, $p")
3923             or ($dd)=($d=~m,^(.+)/+([^/]+)$,) and makedir($dd,$p) and mkdir($d,$p) #or die;
3924 0 0 0     0 ) and ++$MAKEDIR{$d};
      0        
      0        
      0        
      0        
3925             }
3926              
3927             =head2 md5sum
3928              
3929             B a filename.
3930              
3931             B a string of 32 hexadecimal chars from 0-9 or a-f.
3932              
3933             Example, the md5sum gnu/linux command without options could be implementet like this:
3934              
3935             use Acme::Tools;
3936             print eval{ md5sum($_)." $_\n" } || $@ for @ARGV;
3937              
3938             This sub requires L, which is a core perl-module since
3939             version 5.?.? It does not slurp the files or spawn new processes.
3940              
3941             =cut
3942              
3943             sub md5sum {
3944 2     2 1 18 require Digest::MD5;
3945 2         4 my $fn=shift;
3946 2 100       212 croak "md5sum: $fn is a directory (no md5sum)" if -d $fn;
3947 1 50       34 open my $FH, '<', $fn or croak "Could not open file $fn for md5sum() $!";
3948 1         2 binmode($FH);
3949 1         3 my $r = eval { Digest::MD5->new->addfile($FH)->hexdigest };
  1         19  
3950 1 50       8 croak "md5sum on $fn failed ($@)\n" if $@;
3951 1         16 $r;
3952             }
3953              
3954             =head2 read_conf
3955              
3956             B A file name or a reference to a string with settings in the format described below.
3957              
3958             B A reference to a hash. This hash will have the settings from the file (or stringref).
3959             The hash do not have to be empty beforehand.
3960              
3961             Returns a hash with the settings as in this examples:
3962              
3963             my %conf = read_conf('/etc/your/thing.conf');
3964             print $conf{sectionA}{knobble}; #prints ABC if the file is as shown below
3965             print $conf{sectionA}{gobble}; #prints ZZZ, the last gobble
3966             print $conf{switch}; #prints OK here as well, unsectioned value
3967             print $conf{part2}{password}; #prints oh:no= x
3968              
3969             File use for the above example:
3970              
3971             switch: OK #before first section, the '' (empty) section
3972             [sectionA]
3973             knobble: ABC
3974             gobble: XYZ #this gobble is overwritten by the gobble on the next line
3975             gobble: ZZZ
3976             [part2]
3977             password: oh:no= x #should be better
3978             text: { values starting with { continues
3979             until reaching a line with }
3980              
3981             Everything from # and behind is regarded comments and ignored. Comments can be on any line.
3982             To keep a # char, put a \ in front of it.
3983              
3984             A C< : > or C< = > separates keys and values. Spaces at the beginning or end of lines are
3985             ignored (after removal of #comments), as are any spaces before and after : and = separators.
3986              
3987             Empty lines or lines with no C< : > or C< = > is also ignored. Keys and values can contain
3988             internal spaces and tabs, but not at the beginning or end.
3989              
3990             Multi-line values must start and end with { and }. Using { and } keep spaces at the start
3991             or end in both one-line and multi-line values.
3992              
3993             Sections are marked with C<< [sectionname] >>. Section names, keys and values is case
3994             sensitive. C above the first section or below and empty C<< [] >> is placed
3995             both in the empty section in the returned hash and as top level key/values.
3996              
3997             C can be a simpler alternative to the core module L which has
3998             its own hassles.
3999              
4000             $Acme::Tools::Read_conf_empty_section=1; #default 0 (was 1 in version 0.16)
4001             my %conf = read_conf('/etc/your/thing.conf');
4002             print $conf{''}{switch}; #prints OK with the file above
4003             print $conf{switch}; #prints OK here as well
4004              
4005             =cut
4006              
4007             our $Read_conf_empty_section=0;
4008             sub read_conf {
4009 3     3 1 18 my($fn,$hr)=(@_,{});
4010 3 100       14 my $conf=ref($fn)?$$fn:readfile($fn);
4011 3         101 $conf=~s,\s*(?
4012 3         32 my($section,@l)=('',split"\n",$conf);
4013 3         12 while(@l) {
4014 63         93 my $l=shift@l;
4015 63 100       330 if( $l=~/^\s*\[\s*(.*?)\s*\]/ ) {
    100          
4016 12         22 $section=$1;
4017 12   100     68 $$hr{$1}||={};
4018             }
4019             elsif( $l=~/^\s*([^\:\=]+)[:=]\s*(.*?)\s*$/ ) {
4020 33   66 33   108 my $ml=sub{my$v=shift;$v.="\n".shift@l while $v=~/^\{[^\}]*$/&&@l;$v=~s/^\{(.*)\}\s*$/$1/s;$v=~s,\\#,#,g;$v};
  33         71  
  33         168  
  33         68  
  33         52  
  33         60  
4021 33         71 my $v=&$ml($2);
4022 33 100 66     145 $$hr{$section}{$1}=$v if length($section) or $Read_conf_empty_section;
4023 33 100       175 $$hr{$1}=$v if !length($section);
4024             }
4025             }
4026 3         25 %$hr;
4027             }
4028             # my $incfn=sub{return $1 if $_[0]=~m,^(/.+),;my$f=$fn;$f=~s,[^/]+$,$_[0],;$f};
4029             # s,]+)>,"".readfile(&$incfn($1)),eg; #todo
4030              
4031              
4032             =head2 openstr
4033              
4034             # returned from openstr:
4035             open my $FH, openstr("fil.txt") or die; # fil.txt
4036             open my $FH, openstr("fil.gz") or die; # zcat fil.gz |
4037             open my $FH, openstr("fil.bz2") or die; # bzcat fil.bz2 |
4038             open my $FH, openstr("fil.xz") or die; # xzcat fil.xz |
4039             open my $FH, openstr(">fil.txt") or die; # > fil.txt
4040             open my $FH, openstr(">fil.gz") or die; # | gzip > fil.gz
4041             open my $FH, openstr(">fil.bz2") or die; # | bzip2 > fil.bz2
4042             open my $FH, openstr(">fil.xz") or die; # | xz > fil.bz2
4043              
4044             Environment variable PATH is used. So in the examples above, /bin/gzip
4045             is returned instead of gzip if /bin is the first directory in
4046             $ENV{PATH} containing an executable file gzip. Dirs /usr/bin, /bin and
4047             /usr/local/bin is added to PATH in openstr(). They are checked even if
4048             PATH is empty.
4049              
4050             =cut
4051              
4052             our @Openstrpath=(grep$_,split(":",$ENV{PATH}),qw(/usr/bin /bin /usr/local/bin));
4053             sub openstr {
4054 14     14 1 4221 my($fn,$ext)=(shift()=~/^(.*?(?:\.(t?gz|bz2|xz))?)$/i);
4055 14 100       389 return $fn if !$ext;
4056 6 50   6   42 my $prog=sub{@Openstrpath or return $_[0];(grep -x$_, map "$_/$_[0]", @Openstrpath)[0] or die};
  6 50       26  
  6         108929  
4057             $fn =~ /^\s*>/
4058             ? "| ".(&$prog({qw/tgz gzip gz gzip bz2 bzip2 xz xz/ }->{lc($ext)})).$fn
4059 6 100       89 : &$prog({qw/tgz zcat gz zcat bz2 bzcat xz xzcat/}->{lc($ext)})." $fn |";
4060             }
4061              
4062             =head1 TIME FUNCTIONS
4063              
4064             =head2 tms - timestring, works somewhat like the Gnu/Linux C command and Oracle's C
4065              
4066             Converts timestamps to more readable forms of time strings.
4067              
4068             Converts seconds since I and time strings on the form C to other forms.
4069              
4070             B One, two or three arguments.
4071              
4072             B A format string.
4073              
4074             B An epock C number or a time
4075             string of the form YYYYMMDD-HH24:MI:SS or YYYYMMDDTHH:MI:SS or
4076             YYYY-MM-DDTHH:MI:SS (in which T is litteral and HH is the 24-hour
4077             version of hours) or YYYYMMDD. Uses the current C if the
4078             second argument is missing.
4079              
4080             TODO: Formats with % as in C (C<%Y%m%d> and so on)
4081              
4082             B True or false. If true and first argument
4083             is eight digits: Its interpreted as a date like YYYYMMDD time string,
4084             not an epoch time. If true and first argument is six digits its
4085             interpreted as a date like DDMMYY (not YYMMDD!).
4086              
4087             B a date or clock string on the wanted form.
4088              
4089             B
4090              
4091             Prints C<< 3. july 1997 >> if thats the dato today:
4092              
4093             perl -MAcme::Tools -le 'print timestr("D. month YYYY")'
4094              
4095             print tms("HH24:MI"); # prints 23:55 if thats the time now
4096             tms("HH24:MI",time()); # ...same,since time() is the default
4097             tms("HH:MI",time()-5*60); # 23:50 if that was the time 5 minutes ago
4098             tms("HH:MI",time()-5*60*60); # 18:55 if thats the time 5 hours ago
4099             tms("Day Month Dth YYYY HH:MI"); # Saturday July 1st 2004 23:55 (big S, big J)
4100             tms("Day D. Month YYYY HH:MI"); # Saturday 8. July 2004 23:55 (big S, big J)
4101             tms("DAY D. MONTH YYYY HH:MI"); # SATURDAY 8. JULY 2004 23:55 (upper)
4102             tms("dy D. month YYYY HH:MI"); # sat 8. july 2004 23:55 (small s, small j)
4103             tms("Dy DD. MON YYYY HH12:MI am"); # Sat 08. JUL 2004 11:55 pm (HH12, am becomes pm if after 12)
4104             tms("DD-MON-YYYY"); # 03-MAY-2004 (mon, english)
4105              
4106             The following list of codes in the first argument will be replaced:
4107              
4108             YYYY Year, four digits
4109             YY Year, two digits, i.e. 04 instead of 2004
4110             yyyy Year, four digits, but nothing if its the current year
4111             YYYY|HH:MI Year if its another year than the current, a time in hours and minutes elsewise
4112             MM Month, two digits. I.e. 08 for August
4113             DD Day of month, two digits. I.e. 01 (not 1) for the first day in a month
4114             D Day of month, one digit. I.e. 1 (not 01)
4115             HH Hour. From 00 to 23.
4116             HH24 Same as HH.
4117             HH12 12 becomes 12 (never 00), 13 becomes 01, 14 02 and so on.
4118             Note: 00 after midnight becomes 12 (am). Tip: always include the code
4119             am in a format string that uses HH12.
4120             MI Minutt. Fra 00 til 59.
4121             SS Sekund. Fra 00 til 59.
4122             am Becomes am or pm
4123             pm Same
4124             AM Becomes AM or PM (upper case)
4125             PM Same
4126            
4127             Month The full name of the month in English from January to December
4128             MONTH Same in upper case (JANUARY)
4129             month Same in lower case (january)
4130             Mont Jan Feb Mars Apr May June July Aug Sep Oct Nov Dec
4131             Mont. Jan. Feb. Mars Apr. May June July Aug. Sep. Oct. Nov. Dec. (always four chars)
4132             Mon Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec (always three chars)
4133            
4134             Day The full name of the weekday. Sunday to Saturday
4135             Dy Three letters: Sun Mon Tue Wed Thu Fri Sat
4136             DAY Upper case
4137             DY Upper case
4138             Dth 1st 2nd 3rd 4th 5th ... 11th 12th ... 20th 21st 22nd 23rd 24th ... 30th 31st
4139            
4140             WW Week number of the year 01-53 according to the ISO8601-definition (which most countries uses)
4141             WWUS Week number of the year 01-53 according to the most used definition in the USA.
4142             Other definitions also exists.
4143              
4144             epoch Converts a time string from YYYYMMDD-HH24:MI:SS, YYYYMMDD-HH24:MI:SS, YYYYMMDDTHH:MI:SS,
4145             YYYY-MM-DDTHH:MI:SS or YYYYMMDD to the number of seconds since January 1st 1970.
4146             Commonly known as the Unix epoch.
4147            
4148             JDN Julian day number. Integer. The number of days since the day starting at noon on January 1 4713 BC
4149             JD Same as JDN but a float accounting for the time of day
4150            
4151             TODO: sub smt() (tms backward... or something better named, converts the other way)
4152             As to_date and to_char in Oracle. Se maybe L instead
4153              
4154             B (optional) Is_date. False|true, default false. If true, the second argument is
4155             interpreted as a date of the form YYYYMMDD, not as a number of seconds since epoch (January 1st 1970).
4156              
4157             =cut
4158              
4159             #Se også L og L
4160              
4161             our $Tms_pattern;
4162             our %Tms_str=
4163             ('MÅNED' => [4, 'JANUAR','FEBRUAR','MARS','APRIL','MAI','JUNI','JULI',
4164             'AUGUST','SEPTEMBER','OKTOBER','NOVEMBER','DESEMBER' ],
4165             'Måned' => [4, 'Januar','Februar','Mars','April','Mai','Juni','Juli',
4166             'August','September','Oktober','November','Desember'],
4167             'måned' => [4, 'januar','februar','mars','april','mai','juni','juli',
4168             'august','september','oktober','november','desember'],
4169             'MÅNE.' => [4, 'JAN.','FEB.','MARS','APR.','MAI','JUNI','JULI','AUG.','SEP.','OKT.','NOV.','DES.'],
4170             'Måne.' => [4, 'Jan.','Feb.','Mars','Apr.','Mai','Juni','Juli','Aug.','Sep.','Okt.','Nov.','Des.'],
4171             'måne.' => [4, 'jan.','feb.','mars','apr.','mai','juni','juli','aug.','sep.','okt.','nov.','des.'],
4172             'MÅNE' => [4, 'JAN','FEB','MARS','APR','MAI','JUNI','JULI','AUG','SEP','OKT','NOV','DES'],
4173             'Måne' => [4, 'Jan','Feb','Mars','Apr','Mai','Juni','Juli','Aug','Sep','Okt','Nov','Des'],
4174             'måne' => [4, 'jan','feb','mars','apr','mai','juni','juli','aug','sep','okt','nov','des'],
4175             'MÅN' => [4, 'JAN','FEB','MAR','APR','MAI','JUN','JUL','AUG','SEP','OKT','NOV','DES'],
4176             'Mån' => [4, 'Jan','Feb','Mar','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Des'],
4177             'mån' => [4, 'jan','feb','mar','apr','mai','jun','jul','aug','sep','okt','nov','des'],
4178             'MONTH' => [4, 'JANUARY','FEBRUARY','MARCH','APRIL','MAY','JUNE','JULY',
4179             'AUGUST','SEPTEMBER','OCTOBER','NOVEMBER','DECEMBER'],
4180             'Month' => [4, 'January','February','March','April','May','June','July',
4181             'August','September','October','November','December'],
4182             'month' => [4, 'january','february','march','april','may','june','july',
4183             'august','september','october','november','december'],
4184             'MONT.' => [4, 'JAN.','FEB.','MAR.','APR.','MAY','JUNE','JULY','AUG.','SEP.','OCT.','NOV.','DEC.'],
4185             'Mont.' => [4, 'Jan.','Feb.','Mar.','Apr.','May','June','July','Aug.','Sep.','Oct.','Nov.','Dec.'],
4186             'mont.' => [4, 'jan.','feb.','mar.','apr.','may','june','july','aug.','sep.','oct.','nov.','dec.'],
4187             'MONT' => [4, 'JAN','FEB','MAR','APR','MAY','JUNE','JULY','AUG','SEP','OCT','NOV','DEC'],
4188             'Mont' => [4, 'Jan','Feb','Mar','Apr','May','June','July','Aug','Sep','Oct','Nov','Dec'],
4189             'mont' => [4, 'jan','feb','mar','apr','may','june','july','aug','sep','oct','nov','dec'],
4190             'MON' => [4, 'JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC'],
4191             'Mon' => [4, 'Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
4192             'mon' => [4, 'jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec'],
4193             'DAY' => [6, 'SUNDAY','MONDAY','TUESDAY','WEDNESDAY','THURSDAY','FRIDAY','SATURDAY'],
4194             'Day' => [6, 'Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
4195             'day' => [6, 'sunday','monday','tuesday','wednesday','thursday','friday','saturday'],
4196             'DY' => [6, 'SUN','MON','TUE','WED','THU','FRI','SAT'],
4197             'Dy' => [6, 'Sun','Mon','Tue','Wed','Thu','Fri','Sat'],
4198             'dy' => [6, 'sun','mon','tue','wed','thu','fri','sat'],
4199             'DAG' => [6, 'SØNDAG','MANDAG','TIRSDAG','ONSDAG','TORSDAG','FREDAG','LØRDAG'],
4200             'Dag' => [6, 'Søndag','Mandag','Tirsdag','Onsdag','Torsdag','Fredag','Lørdag'],
4201             'dag' => [6, 'søndag','mandag','tirsdag','onsdag','torsdag','fredag','lørdag'],
4202             'DG' => [6, 'SØN','MAN','TIR','ONS','TOR','FRE','LØR'],
4203             'Dg' => [6, 'Søn','Man','Tir','Ons','Tor','Fre','Lør'],
4204             'dg' => [6, 'søn','man','tir','ons','tor','fre','lør'],
4205             );
4206             my $_tms_inited=0;
4207             sub tms_init {
4208 1 50   1 0 7 return if $_tms_inited++;
4209 1         5 for(qw(MAANED Maaned maaned MAAN Maan maan),'MAANE.','Maane.','maane.'){
4210 9         36 $Tms_str{$_}=$Tms_str{replace($_,"aa","å","AA","Å")};
4211             }
4212 45         121 $Tms_pattern=join("|",map{quotemeta($_)}
4213 1         23 sort{length($b)<=>length($a)}
  197         402  
4214             keys %Tms_str);
4215             #uten sort kan "måned" bli "mared", fordi "mån"=>"mar"
4216             }
4217              
4218       0 0   sub totime {
4219              
4220             }
4221              
4222             sub date_ok {
4223 0     0 0 0 my($y,$m,$d)=@_;
4224 0 0 0     0 return date_ok($1,$2,$3) if @_==1 and $_[0]=~/^(\d{4})(\d\d)(\d\d)$/;
4225 0 0       0 return 0 if $y!~/^\d\d\d\d$/;
4226 0 0 0     0 return 0 if $m<1||$m>12||$d<1||$d>(31,$y%4||$y%100==0&&$y%400?28:29,31,30,31,30,31,31,30,31,30,31)[$m-1];
    0 0        
      0        
      0        
4227 0         0 return 1;
4228             }
4229              
4230             sub weeknum {
4231 0 0   0 0 0 return weeknum(tms('YYYYMMDD')) if @_<1;
4232 0 0 0     0 return weeknum($1,$2,$3) if @_==1 and $_[0]=~/^(\d{4})(\d\d)(\d\d)$/;
4233 0         0 my($year,$month,$day)= @_;
4234 0         0 eval{
4235 0 0       0 if(@_<2){
    0          
4236 0 0       0 if($year=~/^\d{8}$/) { ($year,$month,$day)=unpack("A4A2A2",$year) }
  0 0       0  
4237 0         0 elsif($year>99999999){ ($year,$month,$day)=(localtime($year))[5,4,3]; $year+=1900; $month++ }
  0         0  
  0         0  
4238 0         0 else {die}
4239             }
4240 0         0 elsif(@_!=3){croak}
4241 0 0       0 croak if !date_ok(sprintf("%04d%02d%02d",$year,$month,$day));
4242             };
4243 0 0       0 croak "ERROR: Wrong args Acme::Tools::weeknum(".join(",",@_).")" if $@;
4244 28     28   23013 use integer;#heltallsdivisjon
  28         303  
  28         158  
4245 0         0 my $y=$year+4800-(14-$month)/12;
4246 0         0 my $j=$day+(153*($month+(14-$month)/12*12-3)+2)/5+365*$y+$y/4-$y/100+$y/400-32045;
4247 0         0 my $d=($j+31741-$j%7)%146097%36524%1461;
4248 0         0 return (($d-$d/1460)%365+$d/1460)/7+1;
4249             }
4250              
4251             sub tms {
4252 40 50 66 40 1 56004 return undef if @_>1 and not defined $_[1]; #time=undef => undef
4253 40 100       107 if(@_==1){
4254 2         15 my @lt=localtime();
4255 2 50       13 $_[0] eq 'YYYY' and return 1900+$lt[5];
4256 2 50       9 $_[0] eq 'YYYYMMDD' and return sprintf("%04d%02d%02d",1900+$lt[5],1+$lt[4],$lt[3]);
4257 2 100 66     56 $_[0] =~ $Re_isnum and @lt=localtime($_[0]) and return sprintf("%04d%02d%02d-%02d:%02d:%02d",1900+$lt[5],1+$lt[4],@lt[3,2,1,0]);
4258             }
4259 39         72 my($format,$time,$is_date)=@_;
4260 39 100       96 $time=time_fp() if !defined$time;
4261 39 100 100     326 ($time,$format)=($format,$time) if @_>=2 and $format=~/^[\d+\:\-\.]+$/; #swap /hm/
4262 39         203 my @lt=localtime($time);
4263             #todo? $is_date=0 if $time=~s/^\@(\-?\d)/$1/; #@n where n is sec since epoch makes it clear that its not a formatted, as in `date`
4264             #todo? date --date='TZ="America/Los_Angeles" 09:00 next Fri' #`info date`
4265             # Fri Nov 13 18:00:00 CET 2015
4266             #date --date="next Friday" #--date or -d
4267             #date --date="last friday"
4268             #date --date="2 days ago"
4269             #date --date="yesterday" #or tomorrow
4270             #date --date="-1 day" #date --date='10 week'
4271              
4272 39 50       102 if( $is_date ){
4273 0 0   0   0 my $yy2c=sub{10+$_[0]>$lt[5]%100?"20":"19"}; #hm 10+
  0         0  
4274 0 0       0 $time=totime(&$yy2c($1)."$1$2$3")."000000" if $time=~/^(\d\d)(\d\d)(\d\d)$/;
4275 0 0       0 $time=totime("$1$2${3}000000") if $time=~/^((?:18|19|20)\d\d)(\d\d)(\d\d)$/; #hm 18-20?
4276             }
4277             else {
4278 39 50       141 $time = yyyymmddhh24miss_time("$1$2$3$4$5$6") #yyyymmddhh24miss_time ???
4279             if $time=~/^((?:19|20|18)\d\d) #yyyy
4280             (0[1-9]|1[012]) #mm
4281             (0[1-9]|[12]\d|3[01]) \-? #dd
4282             ([01]\d|2[0-3]) \:? #hh24
4283             ([0-5]\d) \:? #mi
4284             ([0-5]\d) $/x; #ss
4285             }
4286 39 100       78 tms_init() if !$_tms_inited;
4287 39 100       108 return sprintf("%04d%02d%02d-%02d:%02d:%02d",1900+$lt[5],1+$lt[4],@lt[3,2,1,0]) if !$format;
4288 38         463 my %p=('%'=>'%',
4289             a=>'Dy',
4290             A=>'Day',
4291             b=>'Mon',
4292             b=>'Month',
4293             c=>'Dy Mon D HH:MI:SS YYYY',
4294             C=>'CC',
4295             d=>'DD',
4296             D=>'MM/DD/YY',
4297             e=>'D',
4298             F=>'YYYY-MM-DD',
4299             #G=>'',
4300             h=>'Month', H=>'HH24', I=>'HH12',
4301             j=>'DoY', #day of year
4302             k=>'H24', _H=>'H24',
4303             l=>'H12', _I=>'H12',
4304             m=>'MM', M=>'MI',
4305             n=>"\n",
4306             #N=>'NS', #sprintf%09d,1e9*(time_fp()-time()) #000000000..999999999
4307             p=>'AM', #AM|PM upper (yes, opposite: date +%H%M%S%P%p)
4308             P=>'am', #am|pm lower
4309             S=>'SS',
4310             t=>"\t",
4311             T=>'HH24:MI:SS',
4312             u=>'DoW', #day of week 1..7, 1=mon 7=sun
4313             w=>'DoW0', #day of week 0..6, 1=mon 0=sun
4314             #U=>'WoYs', #week num of year 00..53, sunday as first day of week
4315             #V=>'UKE', #ISO week num of year 01..53, monday as first day of week
4316             #W=>'WoYm', #week num of year 00..53, monday as first day of week, not ISO!
4317             #x=>$ENV{locale's date representation}, #e.g. MM/DD/YY
4318             #X=>$ENV{locale's time representation}, #e.g. HH/MI/SS
4319             y=>'YY',
4320             Y=>'YYYY',
4321             #z=>'TZHHMI', #time zone hour minute e.g. -0430
4322             #':z'=>'TZHH:MI',
4323             #'::z'=>'TZHH:MI:SS',
4324             #':::z'=>'TZ', #number of :'s necessary precision, e.g. -02 or +03:30
4325             #Z=>'TZN', #e.g. CET, EDT, ...
4326             );
4327 38         260 my $pkeys=join"|",keys%p;
4328 38         1641 $format=~s,\%($pkeys),$p{$1},g;
4329 38         459 $format=~s/($Tms_pattern)/$Tms_str{$1}[1+$lt[$Tms_str{$1}[0]]]/g;
4330 38         92 $format=~s/YYYY / 1900+$lt[5] /gxe;
  13         44  
4331 38 0       70 $format=~s/(\s?)yyyy / $lt[5]==(localtime)[5]?"":$1.(1900+$lt[5])/gxe;
  0         0  
4332 38         65 $format=~s/YY / sprintf("%02d",$lt[5]%100) /gxei;
  1         5  
4333 38         67 $format=~s|CC | sprintf("%02d",(1900+$lt[5])/100) |gxei;
  2         10  
4334 38         59 $format=~s/MM / sprintf("%02d",$lt[4]+1) /gxe;
  5         25  
4335 38         56 $format=~s/mm / sprintf("%d",$lt[4]+1) /gxe;
  0         0  
4336 38         57 $format=~s,M/ , ($lt[4]+1).'/' ,gxe;
  2         7  
4337 38         52 $format=~s,/M , '/'.($lt[4]+1) ,gxe;
  1         4  
4338 38         62 $format=~s/DD / sprintf("%02d",$lt[3]) /gxe;
  6         25  
4339 38         110 $format=~s/d0w|dow0 / $lt[6] /gxei;
  4         11  
4340 38 100       67 $format=~s/dow / $lt[6]?$lt[6]:7 /gxei;
  2         8  
4341 38         81 $format=~s/d0y|doy0 / $lt[7] /gxei; #0-364 (365 leap)
  2         7  
4342 38         117 $format=~s/doy / $lt[7]+1 /gxei; #1-365 (366 leap)
  1         4  
4343 38         98 $format=~s/D(?![AaGgYyEeNn]) / $lt[3] /gxe; #EN pga desember og wednesday
  5         15  
4344 38         55 $format=~s/dd / sprintf("%d",$lt[3]) /gxe;
  0         0  
4345 38 100 50     88 $format=~s/hh12|HH12 / sprintf("%02d",$lt[2]<13?$lt[2]||12:$lt[2]-12)/gxe;
  8         51  
4346 38         86 $format=~s/HH24|HH24|HH|hh / sprintf("%02d",$lt[2]) /gxe;
  4         22  
4347 38         77 $format=~s/MI / sprintf("%02d",$lt[1]) /gxei;
  12         42  
4348 38   100     68 $format=~s{SS\.([1-9]) }{ sprintf("%0*.$1f",3+$1,$lt[0]+(repl($time,qr/^[^\.]+/)||0)) }gxei;
  3         21  
4349 38         64 $format=~s/SS / sprintf("%02d",$lt[0]) /gxei;
  4         16  
4350 38 100       77 $format=~s/am|pm / $lt[2]<13 ? 'am' : 'pm' /gxe;
  4         14  
4351 38 100       75 $format=~s/AM|PM / $lt[2]<13 ? 'AM' : 'PM' /gxe;
  4         13  
4352 38         107 $format=~s/WWI|WW / sprintf("%02d",weeknum($time)) /gxei;
  0         0  
4353 38         60 $format=~s/W / weeknum($time) /gxei;
  0         0  
4354 38         323 $format;
4355             }
4356              
4357             =head2 easter
4358              
4359             Input: A year (a four digit number)
4360              
4361             Output: array of two numbers: day and month of Easter Sunday that year. Month 3 means March and 4 means April.
4362              
4363             sub easter { use integer;my$Y=shift;my$C=$Y/100;my$L=($C-$C/4-($C-($C-17)/25)/3+$Y%19*19+15)%30;
4364             (($L-=$L>28||($L>27?1-(21-$Y%19)/11:0))-=($Y+$Y/4+$L+2-$C+$C/4)%7)<4?($L+28,3):($L-3,4) }
4365              
4366             ...is a "golfed" version of Oudins algorithm (1940) L
4367             (see also http://www.smart.net/~mmontes/ec-cal.html )
4368              
4369             Valid for any Gregorian year. Dates repeat themselves after 70499183
4370             lunations = 2081882250 days = ca 5699845 years. However, our planet will
4371             by then have a different rotation and spin time...
4372              
4373             Example:
4374              
4375             ( $day, $month ) = easter( 2012 ); # $day == 8 and $month == 4
4376              
4377             Example 2:
4378              
4379             my @e=map sprintf("%02d%02d", reverse(easter($_))), 1800..300000;
4380             print "First: ".min(@e)." Last: ".max(@e)."\n"; # First: 0322 Last: 0425
4381              
4382             =cut
4383              
4384 28     28 1 53963 sub easter { use integer;my$Y=shift;my$C=$Y/100;my$L=($C-$C/4-($C-($C-17)/25)/3+$Y%19*19+15)%30;
  28     5000   52  
  28         124  
  5000         11620  
  5000         6188  
  5000         8536  
4385 5000 100 66     24827 (($L-=$L>28||($L>27?1-(21-$Y%19)/11:0))-=($Y+$Y/4+$L+2-$C+$C/4)%7)<4?($L+28,3):($L-3,4) }
4386              
4387              
4388             =head2 time_fp
4389              
4390             No input arguments.
4391              
4392             Return the same number as perls C except with decimals (fractions of a second, _fp as in floating point number).
4393              
4394             print time_fp(),"\n";
4395             print time(),"\n";
4396              
4397             Could write:
4398              
4399             1116776232.38632
4400              
4401             ...if that is the time now.
4402              
4403             Or just:
4404              
4405             1116776232
4406              
4407             ...from perl's internal C if C isn't installed and available.
4408              
4409              
4410             =cut
4411              
4412             sub time_fp { # {return 0+gettimeofday} is just as well?
4413 12416 50   12416 1 19116 eval{ require Time::HiRes } or return time();
  12416         75841  
4414 12416         47644 my($sec,$mic)=Time::HiRes::gettimeofday();
4415 12416         53145 return $sec+$mic/1e6; #1e6 not portable?
4416             }
4417              
4418             =head2 sleep_fp
4419              
4420             sleep_fp() work as the built in C<< sleep() >> but also accepts fractional seconds:
4421              
4422             sleep_fp(0.020); # sleeps for 20 milliseconds
4423              
4424             Sub sleep_fp do a C, thus it might take some
4425             extra time the first call. To avoid that, add C<< use Time::HiRes >>
4426             to your code. Sleep_fp should not be trusted for accuracy to more than
4427             a tenth of a second. Virtual machines tend to be less accurate (sleep
4428             longer) than physical ones. This was tested on VMware and RHEL
4429             (Linux). See also L.
4430              
4431             =head2 sleeps
4432              
4433             =head2 sleepms
4434              
4435             =head2 sleepus
4436              
4437             =head2 sleepns
4438              
4439             sleep_fp(0.020); #sleeps for 20 milliseconds
4440             sleeps(0.020); #sleeps for 20 milliseconds, sleeps() is a synonym to sleep_fp()
4441             sleepms(20); #sleeps for 20 milliseconds
4442             sleepus(20000); #sleeps for 20000 microseconds = 20 milliseconds
4443             sleepns(20000000); #sleeps for 20 million nanoseconds = 20 milliseconds
4444              
4445             =cut
4446              
4447 13 50   13 1 81 sub sleep_fp { eval{require Time::HiRes} or (sleep(shift()),return);Time::HiRes::sleep(shift()) }
  13         156  
  13         221802  
4448 1 50   1 1 12 sub sleeps { eval{require Time::HiRes} or (sleep(shift()),return);Time::HiRes::sleep(shift()) }
  1         14  
  1         10162  
4449 1 50   1 1 18 sub sleepms { eval{require Time::HiRes} or (sleep(shift()/1e3),return);Time::HiRes::sleep(shift()/1e3) }
  1         24  
  1         10168  
4450 1 50   1 1 14 sub sleepus { eval{require Time::HiRes} or (sleep(shift()/1e6),return);Time::HiRes::sleep(shift()/1e6) }
  1         21  
  1         10158  
4451 1 50   1 1 13 sub sleepns { eval{require Time::HiRes} or (sleep(shift()/1e9),return);Time::HiRes::sleep(shift()/1e9) }
  1         19  
  1         10140  
4452              
4453             =head2 eta
4454              
4455             Estimated time of arrival (ETA).
4456              
4457             for(@files){
4458             ...do work on file...
4459             my $eta = eta( ++$i, 0+@files ); # file now, number of files
4460             print "" . localtime($eta);
4461             }
4462              
4463             ..DOC MISSING..
4464              
4465             =head2 etahhmm
4466              
4467             ...NOT YET
4468              
4469             =cut
4470              
4471             #http://en.wikipedia.org/wiki/Kalman_filter god idé?
4472             our %Eta;
4473             our $Eta_forgetfulness=2;
4474             sub eta {
4475 2004 100   2004 1 15296 my($id,$pos,$end,$time_fp)=( @_==2 ? (join(";",caller()),@_) : @_ );
4476 2004   66     4544 $time_fp||=time_fp();
4477 2004   100     4853 my $a=$Eta{$id}||=[];
4478 2004         4265 push @$a, [$pos,$time_fp];
4479 2004 100       5365 @$a=@$a[map$_*2,0..@$a/2] if @$a>40; #hm 40
4480 2004 100 100     9090 splice(@$a,-2,1) if @$a>1 and $$a[-2][0]==$$a[-1][0]; #same pos as last
4481 2004 100       4117 return undef if @$a<2;
4482 2001         2410 my @eta;
4483 2001         3755 for(2..@$a){
4484 58602         158569 push @eta, $$a[-1][1] + ($end-$$a[-1][0]) * ($$a[-1][1]-$$a[-$_][1])/($$a[-1][0]-$$a[-$_][0]);
4485             }
4486 2001         2940 my($sum,$sumw,$w)=(0,0,1);
4487 2001         3107 for(@eta){
4488 58602         74926 $sum+=$w*$_;
4489 58602         70451 $sumw+=$w;
4490 58602         83675 $w/=$Eta_forgetfulness;
4491             }
4492 2001         2729 my $avg=$sum/$sumw;
4493 2001         6189 return $avg;
4494             # return avg(@eta);
4495             #return $$a[-1][1] + ($end-$$a[-1][0]) * ($$a[-1][1]-$$a[-2][1])/($$a[-1][0]-$$a[-2][0]);
4496 0         0 1;
4497             }
4498              
4499             =head2 sleep_until
4500              
4501             sleep_until(0.5) sleeps until half a second has passed since the last
4502             call to sleep_until. This example starts the next job excactly ten
4503             seconds after the last job started even if the last job lasted for a
4504             while (but not more than ten seconds):
4505              
4506             for(@jobs){
4507             sleep_until(10);
4508             print localtime()."\n";
4509             ...heavy job....
4510             }
4511              
4512             Might print:
4513              
4514             Thu Jan 12 16:00:00 2012
4515             Thu Jan 12 16:00:10 2012
4516             Thu Jan 12 16:00:20 2012
4517              
4518             ...and so on even if the C<< ...heavy job... >>-part takes more than a
4519             second to complete. Whereas if sleep(10) was used, each job would
4520             spend more than ten seconds in average since the work time would be
4521             added to sleep(10).
4522              
4523             Note: sleep_until() will remember the time of ANY last call of this sub,
4524             not just the one on the same line in the source code (this might change
4525             in the future). The first call to sleep_until() will be the same as
4526             sleep_fp() or Perl's own sleep() if the argument is an integer.
4527              
4528             =cut
4529              
4530             our $Time_last_sleep_until;
4531             sub sleep_until {
4532 0 0   0 1 0 my $s=@_==1?shift():0;
4533 0         0 my $time=time_fp();
4534 0         0 my $sleep=$s-($time-nvl($Time_last_sleep_until,0));
4535 0         0 $Time_last_sleep_until=time;
4536 0 0       0 sleep_fp($sleep) if $sleep>0;
4537             }
4538              
4539             =head2 leapyear
4540              
4541             B A year. A four digit number.
4542              
4543             B True (1) or false (0) of whether the year is a leap year or
4544             not. (Uses current calendar even for periods before leapyears was used).
4545              
4546             print join(", ",grep leapyear($_), 1900..2014)."\n";
4547              
4548             1904, 1908, 1912, 1916, 1920, 1924, 1928, 1932, 1936, 1940, 1944, 1948, 1952, 1956,
4549             1960, 1964, 1968, 1972, 1976, 1980, 1984, 1988, 1992, 1996, 2000, 2004, 2008, 2012
4550              
4551             Note: 1900 is not a leap year, but 2000 is. Years divided by 100 is a leap year only
4552             if it can be divided by 400.
4553              
4554             =cut
4555              
4556 0 0   0 1 0 sub leapyear{$_[0]%400?$_[0]%100?$_[0]%4?0:1:0:1} #bool
    0          
    0          
4557              
4558             #http://rosettacode.org/wiki/Levenshtein_distance#Perl
4559             our %ldist_cache;
4560             sub ldist {
4561 0     0 0 0 my($s,$t,$l) = @_;
4562 0 0       0 return length($t) if !$s;
4563 0 0       0 return length($s) if !$t;
4564 0 0 0     0 %ldist_cache=() if !$l and 1000<0+%ldist_cache;
4565             $ldist_cache{$s,$t} ||=
4566 0   0     0 do {
4567 0         0 my($s1,$t1) = ( substr($s,1), substr($t,1) );
4568 0 0       0 substr($s,0,1) eq substr($t,0,1)
4569             ? ldist($s1,$t1)
4570             : 1 + min( ldist($s1,$t1,1+$l), ldist($s,$t1,1+$l), ldist($s1,$t,1+$l) );
4571             };
4572             }
4573              
4574             =head1 OTHER
4575              
4576             =head2 nvl
4577              
4578             The I function (or I function)
4579              
4580             C takes two or more arguments. (Oracles nvl-function take just two)
4581              
4582             Returns the value of the first input argument with length() > 0.
4583              
4584             Return I if there is no such input argument.
4585              
4586             In perl 5.10 and perl 6 this will most often be easier with the C< //
4587             > operator, although C and C<< // >> treats empty strings C<"">
4588             differently. Sub nvl here considers empty strings and undef the same.
4589              
4590             =cut
4591              
4592             sub nvl {
4593 38 100 66 38 1 285 return $_[0] if defined $_[0] and length($_[0]) or @_==1;
      100        
4594 22 100       83 return $_[1] if @_==2;
4595 9 100       36 return nvl(@_[1..$#_]) if @_>2;
4596 1         4 return undef;
4597             }
4598              
4599             =head2 decode_num
4600              
4601             See L.
4602              
4603             =head2 decode
4604              
4605             C and C works just as Oracles C.
4606              
4607             C and C accordingly uses perl operators C and C<==> for comparison.
4608              
4609             Examples:
4610              
4611             my $a=123;
4612             print decode($a, 123,3, 214,4, $a); # prints 3
4613             print decode($a, 123=>3, 214=>4, $a); # prints 3, same thing since => is synonymous to comma in Perl
4614              
4615             The first argument is tested against the second, fourth, sixth and so on,
4616             and then the third, fifth, seventh and so on is
4617             returned if decode() finds an equal string or number.
4618              
4619             In the above example: 123 maps to 3, 124 maps to 4 and the last argument $a is returned elsewise.
4620              
4621             More examples:
4622              
4623             my $a=123;
4624             print decode($a, 123=>3, 214=>7, $a); # also 3, note that => is synonym for , (comma) in perl
4625             print decode($a, 122=>3, 214=>7, $a); # prints 123
4626             print decode($a, 123.0 =>3, 214=>7); # prints 3
4627             print decode($a, '123.0'=>3, 214=>7); # prints nothing (undef), no last argument default value here
4628             print decode_num($a, 121=>3, 221=>7, '123.0','b'); # prints b
4629              
4630             Sort of:
4631              
4632             decode($string, %conversion, $default);
4633              
4634             The last argument is returned as a default if none of the keys in the keys/value-pairs matched.
4635              
4636             A more perl-ish and often faster way of doing the same:
4637              
4638             {123=>3, 214=>7}->{$a} || $a # (beware of 0)
4639              
4640             =cut
4641              
4642             sub decode {
4643 4 50   4 1 10 croak "Must have a mimimum of two arguments" if @_<2;
4644 4         6 my $uttrykk=shift;
4645 4 50 100     11 if(defined$uttrykk){ shift eq $uttrykk and return shift or shift for 1..@_/2 }
  4   33     37  
4646 0   0     0 else { !defined shift and return shift or shift for 1..@_/2 }
      0        
4647 2         8 return shift;
4648             }
4649              
4650             sub decode_num {
4651 1 50   1 1 5 croak "Must have a mimimum of two arguments" if @_<2;
4652 1         2 my $uttrykk=shift;
4653 1 50 100     3 if(defined$uttrykk){ shift == $uttrykk and return shift or shift for 1..@_/2 }
  1   33     15  
4654 0   0     0 else { !defined shift and return shift or shift for 1..@_/2 }
      0        
4655 0         0 return shift;
4656             }
4657              
4658             =head2 qrlist
4659              
4660             Input: An array of values to be used to test againts for existence.
4661              
4662             Output: A reference to a regular expression. That is a C
4663              
4664             The regex sets $1 if it match.
4665              
4666             Example:
4667              
4668             my @list=qw/ABc XY DEF DEFG XYZ/;
4669             my $filter=qrlist("ABC","DEF","XY."); # makes a regex of it qr/^(\QABC\E|\QDEF\E|\QXY.\E)$/
4670             my @filtered= grep { $_ =~ $filter } @list; # returns DEF and XYZ, but not XYZ because the . char is taken literally
4671              
4672             Note: Filtering with hash lookups are WAY faster.
4673              
4674             Source:
4675              
4676             sub qrlist (@) { my $str=join"|",map quotemeta, @_; qr/^($str)$/ }
4677              
4678             =cut
4679              
4680             sub qrlist (@) {
4681 0     0 1 0 my $str=join"|",map quotemeta,@_;
4682 0         0 return qr/^($str)$/;
4683             }
4684              
4685             =head2 ansicolor
4686              
4687             Perhaps easier to use than L ?
4688              
4689             B One argument. A string where the char C<¤> have special
4690             meaning and is replaced by color codings depending on the letter
4691             following the C<¤>.
4692              
4693             B The same string, but with C<¤letter> replaced by ANSI color
4694             codes respected by many types terminal windows. (xterm, telnet, ssh,
4695             telnet, rlog, vt100, cygwin, rxvt and such...).
4696              
4697             B
4698              
4699             ¤r red
4700             ¤g green
4701             ¤b blue
4702             ¤y yellow
4703             ¤m magenta
4704             ¤B bold
4705             ¤u underline
4706             ¤c clear
4707             ¤¤ reset, quits and returns to default text color.
4708              
4709             B
4710              
4711             print ansicolor("This is maybe ¤ggreen¤¤?");
4712              
4713             Prints I where the word I is shown in green.
4714              
4715             If L is not installed or not found, returns the input
4716             string with every C<¤> including the following code letters
4717             removed. (That is: ansicolor is safe to use even if Term::ANSIColor is
4718             not installed, you just don't get the colors).
4719              
4720             See also L.
4721              
4722             =cut
4723              
4724             sub ansicolor {
4725 0     0 1 0 my $txt=shift;
4726 0 0       0 eval{require Term::ANSIColor} or return replace($txt,qr/¤./);
  0         0  
4727 0         0 my %h=qw/r red g green b blue y yellow m magenta B bold u underline c clear ¤ reset/;
4728 0         0 my $re=join"|",keys%h;
4729 0         0 $txt=~s/¤($re)/Term::ANSIColor::color($h{$1})/ge;
  0         0  
4730 0         0 return $txt;
4731             }
4732              
4733             =head2 ccn_ok
4734              
4735             Checks if a Credit Card number (CCN) has correct control digits according to the LUHN-algorithm from 1960.
4736             This method of control digits is used by MasterCard, Visa, American Express,
4737             Discover, Diners Club / Carte Blanche, JCB and others.
4738              
4739             B
4740              
4741             A credit card number. Can contain non-digits, but they are removed internally before checking.
4742              
4743             B
4744              
4745             Something true or false.
4746              
4747             Or more accurately:
4748              
4749             Returns C (false) if the input argument is missing digits.
4750              
4751             Returns 0 (zero, which is false) is the digits is not correct according to the LUHN algorithm.
4752              
4753             Returns 1 or the name of a credit card company (true either way) if the last digit is an ok control digit for this ccn.
4754              
4755             The name of the credit card company is returned like this (without the C<'> character)
4756              
4757             Returns (wo '') Starts on Number of digits
4758             ------------------------------ ------------------------ ----------------
4759             'MasterCard' 51-55 16
4760             'Visa' 4 13 eller 16
4761             'American Express' 34 eller 37 15
4762             'Discover' 6011 16
4763             'Diners Club / Carte Blanche' 300-305, 36 eller 38 14
4764             'JCB' 3 16
4765             'JCB' 2131 eller 1800 15
4766              
4767             And should perhaps have had:
4768              
4769             'enRoute' 2014 eller 2149 15
4770              
4771             ...but that card uses either another control algorithm or no control
4772             digits at all. So C is never returned here.
4773              
4774             If the control digits is valid, but the input does not match anything in the column C, 1 is returned.
4775              
4776             (This is also the same control digit mechanism used in Norwegian KID numbers on payment bills)
4777              
4778             The first digit in a credit card number is supposed to tell what "industry" the card is meant for:
4779              
4780             MII Digit Value Issuer Category
4781             --------------------------- ----------------------------------------------------
4782             0 ISO/TC 68 and other industry assignments
4783             1 Airlines
4784             2 Airlines and other industry assignments
4785             3 Travel and entertainment
4786             4 Banking and financial
4787             5 Banking and financial
4788             6 Merchandizing and banking
4789             7 Petroleum
4790             8 Telecommunications and other industry assignments
4791             9 National assignment
4792              
4793             ...although this has no meaning to C.
4794              
4795             The first six digits is I, that is the bank
4796             (probably). The rest in the "account number", except the last digits,
4797             which is the control digit. Max length on credit card numbers are 19
4798             digits.
4799              
4800             =cut
4801              
4802             sub ccn_ok {
4803 0     0 1 0 my $ccn=shift(); #credit card number
4804 0         0 $ccn=~s/\D+//g;
4805 0 0       0 if(KID_ok($ccn)){
4806 0 0       0 return "MasterCard" if $ccn=~/^5[1-5]\d{14}$/;
4807 0 0       0 return "Visa" if $ccn=~/^4\d{12}(?:\d{3})?$/;
4808 0 0       0 return "American Express" if $ccn=~/^3[47]\d{13}$/;
4809 0 0       0 return "Discover" if $ccn=~/^6011\d{12}$/;
4810 0 0       0 return "Diners Club / Carte Blanche" if $ccn=~/^3(?:0[0-5]\d{11}|[68]\d{12})$/;
4811 0 0       0 return "JCB" if $ccn=~/^(?:3\d{15}|(?:2131|1800)\d{11})$/;
4812 0         0 return 1;
4813             }
4814             #return "enRoute" if $ccn=~/^(?:2014|2149)\d{11}$/; #ikke LUHN-krav?
4815 0         0 return 0;
4816             }
4817              
4818             =head2 KID_ok
4819              
4820             Checks if a norwegian KID number has an ok control digit.
4821              
4822             To check if a customer has typed the number correctly.
4823              
4824             This uses the LUHN algorithm (also known as mod-10) from 1960 which is also used
4825             internationally in control digits for credit card numbers, and Canadian social security ID numbers as well.
4826              
4827             The algorithm, as described in Phrack (47-8) (a long time hacker online publication):
4828              
4829             "For a card with an even number of digits, double every odd numbered
4830             digit and subtract 9 if the product is greater than 9. Add up all the
4831             even digits as well as the doubled-odd digits, and the result must be
4832             a multiple of 10 or it's not a valid card. If the card has an odd
4833             number of digits, perform the same addition doubling the even numbered
4834             digits instead."
4835              
4836             B A KID-nummer. Must consist of digits 0-9 only, otherwise a die (croak) happens.
4837              
4838             B
4839              
4840             - Returns undef if the input argument is missing.
4841              
4842             - Returns 0 if the control digit (the last digit) does not satify the LUHN/mod-10 algorithm.
4843              
4844             - Returns 1 if ok
4845              
4846             B L
4847              
4848             =cut
4849              
4850             sub KID_ok {
4851 0 0   0 1 0 croak "Non-numeric argument" if $_[0]=~/\D/;
4852 0 0       0 my @k=split//,shift or return undef;
4853 0         0 my $s;$s+=pop(@k)+[qw/0 2 4 6 8 1 3 5 7 9/]->[pop@k] while @k;
  0         0  
4854 0 0       0 $s%10==0?1:0;
4855             }
4856              
4857              
4858              
4859             =head2 range
4860              
4861             B
4862              
4863             One or more numeric arguments:
4864              
4865             First: x (first returned element)
4866              
4867             Second: y (last but not including)
4868              
4869             Third: step, default 1. The step between each returned element
4870              
4871             If a fourth, fifth and so on arguments are given, they change the step for each returned element. As first derivative, second derivative.
4872              
4873             B
4874              
4875             If one argument: returns the array C<(0 .. x-1)>
4876              
4877             If two arguments: returns the array C<(x .. y-1)>
4878              
4879             If three arguments: The default step is 1. Use a third argument to use a different step.
4880              
4881             B
4882              
4883             print join ",", range(11); # prints 0,1,2,3,4,5,6,7,8,9,10 (but not 11)
4884             print join ",", range(2,11); # 2,3,4,5,6,7,8,9,10 (but not 11)
4885             print join ",", range(11,2,-1); # 11,10,9,8,7,6,5,4,3
4886             print join ",", range(2,11,3); # 2,5,8
4887             print join ",", range(11,2,-3); # 11,8,5
4888             print join ",", range(11,2,+3); # prints nothing
4889              
4890             print join ", ",range(2,11,1,0.1); # 2, 3, 4.1, 5.3, 6.6, 8, 9.5 adds 0.1 to step each time
4891             print join ", ",range(2,11,1,0.1,-0.01); # 2, 3, 4.1, 5.29, 6.56, 7.9, 9.3, 10.75
4892              
4893             Note: In the Python language and others, C is a build in iterator (a
4894             generator), not an array. This saves memory for large sets and sometimes time.
4895             Use C in L to get a similar lazy generator in Perl.
4896              
4897             =cut
4898              
4899             sub range {
4900 8 100   8 1 35 return _range_accellerated(@_) if @_>3; #se under
4901 6         13 my($x,$y,$jump)=@_;
4902 6 100       71 return ( 0 .. $x-1 ) if @_==1;
4903 5 100       21 return ( $x .. $y-1 ) if @_==2;
4904 4 50 33     28 croak "Wrong number of arguments or jump==0" if @_!=3 or $jump==0;
4905 4         6 my @r;
4906 4 100       11 if($jump>0){ while($x<$y){ push @r, $x; $x+=$jump } }
  2         8  
  772         856  
  772         1292  
4907 2         6 else { while($x>$y){ push @r, $x; $x+=$jump } }
  12         18  
  12         21  
4908 4         57 return @r;
4909             }
4910              
4911             #jumps derivative, double der., trippled der usw
4912             sub _range_accellerated {
4913 2     2   6 my($x,$y,@jump)=@_;
4914 2         4 my @r;
4915 2 50   0   10 my $test = $jump[0]>=0 ? sub{$x<$y} : sub{$x>$y};
  17         45  
  0         0  
4916 2         6 while(&$test()){
4917 15         23 push @r, $x;
4918 15         18 $x+=$jump[0];
4919 15         50 $jump[$_-1]+=$jump[$_] for 1..$#jump;
4920             }
4921 2         29 return @r;
4922             }
4923              
4924             =head2 permutations
4925              
4926             How many ways (permutations) can six people be placed around a table:
4927              
4928             If one person: one
4929             If two persons: two (they can swap places)
4930             If three persons: six
4931             If four persons: 24
4932             If five persons: 120
4933             If six persons: 720
4934              
4935             The formula is C where the postfix unary operator C, also known as I is defined like:
4936             C. Example: C<5! = 5 * 4 * 3 * 2 * 1 = 120>.Run this to see the 100 first C<< n! >>
4937              
4938             perl -MAcme::Tools -le'$i=big(1);print "$_!=",$i*=$_ for 1..100'
4939              
4940             1! = 1
4941             2! = 2
4942             3! = 6
4943             4! = 24
4944             5! = 120
4945             6! = 720
4946             7! = 5040
4947             8! = 40320
4948             9! = 362880
4949             10! = 3628800
4950             .
4951             .
4952             .
4953             100! = 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
4954              
4955             C takes a list and return a list of arrayrefs for each
4956             of the permutations of the input list:
4957              
4958             permutations('a','b'); #returns (['a','b'],['b','a'])
4959              
4960             permutations('a','b','c'); #returns (['a','b','c'],['a','c','b'],
4961             # ['b','a','c'],['b','c','a'],
4962             # ['c','a','b'],['c','b','a'])
4963              
4964             Up to five input arguments C is probably as fast as it
4965             can be in this pure perl implementation (see source). For more than
4966             five, it could be faster. How fast is it now: Running with different
4967             n, this many time took that many seconds:
4968              
4969             n times seconds
4970             -- ------- ---------
4971             2 100000 0.32
4972             3 10000 0.09
4973             4 10000 0.33
4974             5 1000 0.18
4975             6 100 0.27
4976             7 10 0.21
4977             8 1 0.17
4978             9 1 1.63
4979             10 1 17.00
4980              
4981             If the first argument is a coderef, that sub will be called for each permutation and the return from those calls with be the real return from C. For example this:
4982              
4983             print for permutations(sub{join"",@_},1..3);
4984              
4985             ...will print the same as:
4986              
4987             print for map join("",@$_), permutations(1..3);
4988              
4989             ...but the first of those two uses less RAM if 3 has been say 9.
4990             Changing 3 with 10, and many computers hasn't enough memory
4991             for the latter.
4992              
4993             The examples prints:
4994              
4995             123
4996             132
4997             213
4998             231
4999             312
5000             321
5001              
5002             If you just want to say calculate something on each permutation,
5003             but is not interested in the list of them, you just don't
5004             take the return. That is:
5005              
5006             my $ant;
5007             permutations(sub{$ant++ if $_[-1]>=$_[0]*2},1..9);
5008              
5009             ...is the same as:
5010              
5011             $$_[-1]>=$$_[0]*2 and $ant++ for permutations(1..9);
5012              
5013             ...but the first uses next to nothing of memory compared to the latter. They have about the same speed.
5014             (The examples just counts the permutations where the last number is at least twice as large as the first)
5015              
5016             C was created to find all combinations of a persons
5017             name. This is useful in "fuzzy" name searches with
5018             L if you can not be certain what is first, middle
5019             and last names. In foreign or unfamiliar names it can be difficult to
5020             know that.
5021              
5022             =cut
5023              
5024             #TODO: se test_perl.pl
5025              
5026             sub permutations {
5027 2 50   2 1 16 my $code=ref($_[0]) eq 'CODE' ? shift() : undef;
5028 2 50 33     11 $code and @_<6 and return map &$code(@$_),permutations(@_);
5029              
5030 2 50       7 return [@_] if @_<2;
5031              
5032 2 100       19 return ([@_[0,1]],[@_[1,0]]) if @_==2;
5033              
5034 1 50       19 return ([@_[0,1,2]],[@_[0,2,1]],[@_[1,0,2]],
5035             [@_[1,2,0]],[@_[2,0,1]],[@_[2,1,0]]) if @_==3;
5036              
5037 0 0       0 return ([@_[0,1,2,3]],[@_[0,1,3,2]],[@_[0,2,1,3]],[@_[0,2,3,1]],
5038             [@_[0,3,1,2]],[@_[0,3,2,1]],[@_[1,0,2,3]],[@_[1,0,3,2]],
5039             [@_[1,2,0,3]],[@_[1,2,3,0]],[@_[1,3,0,2]],[@_[1,3,2,0]],
5040             [@_[2,0,1,3]],[@_[2,0,3,1]],[@_[2,1,0,3]],[@_[2,1,3,0]],
5041             [@_[2,3,0,1]],[@_[2,3,1,0]],[@_[3,0,1,2]],[@_[3,0,2,1]],
5042             [@_[3,1,0,2]],[@_[3,1,2,0]],[@_[3,2,0,1]],[@_[3,2,1,0]]) if @_==4;
5043              
5044 0 0       0 return ([@_[0,1,2,3,4]],[@_[0,1,2,4,3]],[@_[0,1,3,2,4]],[@_[0,1,3,4,2]],[@_[0,1,4,2,3]],
5045             [@_[0,1,4,3,2]],[@_[0,2,1,3,4]],[@_[0,2,1,4,3]],[@_[0,2,3,1,4]],[@_[0,2,3,4,1]],
5046             [@_[0,2,4,1,3]],[@_[0,2,4,3,1]],[@_[0,3,1,2,4]],[@_[0,3,1,4,2]],[@_[0,3,2,1,4]],
5047             [@_[0,3,2,4,1]],[@_[0,3,4,1,2]],[@_[0,3,4,2,1]],[@_[0,4,1,2,3]],[@_[0,4,1,3,2]],
5048             [@_[0,4,2,1,3]],[@_[0,4,2,3,1]],[@_[0,4,3,1,2]],[@_[0,4,3,2,1]],[@_[1,0,2,3,4]],
5049             [@_[1,0,2,4,3]],[@_[1,0,3,2,4]],[@_[1,0,3,4,2]],[@_[1,0,4,2,3]],[@_[1,0,4,3,2]],
5050             [@_[1,2,0,3,4]],[@_[1,2,0,4,3]],[@_[1,2,3,0,4]],[@_[1,2,3,4,0]],[@_[1,2,4,0,3]],
5051             [@_[1,2,4,3,0]],[@_[1,3,0,2,4]],[@_[1,3,0,4,2]],[@_[1,3,2,0,4]],[@_[1,3,2,4,0]],
5052             [@_[1,3,4,0,2]],[@_[1,3,4,2,0]],[@_[1,4,0,2,3]],[@_[1,4,0,3,2]],[@_[1,4,2,0,3]],
5053             [@_[1,4,2,3,0]],[@_[1,4,3,0,2]],[@_[1,4,3,2,0]],[@_[2,0,1,3,4]],[@_[2,0,1,4,3]],
5054             [@_[2,0,3,1,4]],[@_[2,0,3,4,1]],[@_[2,0,4,1,3]],[@_[2,0,4,3,1]],[@_[2,1,0,3,4]],
5055             [@_[2,1,0,4,3]],[@_[2,1,3,0,4]],[@_[2,1,3,4,0]],[@_[2,1,4,0,3]],[@_[2,1,4,3,0]],
5056             [@_[2,3,0,1,4]],[@_[2,3,0,4,1]],[@_[2,3,1,0,4]],[@_[2,3,1,4,0]],[@_[2,3,4,0,1]],
5057             [@_[2,3,4,1,0]],[@_[2,4,0,1,3]],[@_[2,4,0,3,1]],[@_[2,4,1,0,3]],[@_[2,4,1,3,0]],
5058             [@_[2,4,3,0,1]],[@_[2,4,3,1,0]],[@_[3,0,1,2,4]],[@_[3,0,1,4,2]],[@_[3,0,2,1,4]],
5059             [@_[3,0,2,4,1]],[@_[3,0,4,1,2]],[@_[3,0,4,2,1]],[@_[3,1,0,2,4]],[@_[3,1,0,4,2]],
5060             [@_[3,1,2,0,4]],[@_[3,1,2,4,0]],[@_[3,1,4,0,2]],[@_[3,1,4,2,0]],[@_[3,2,0,1,4]],
5061             [@_[3,2,0,4,1]],[@_[3,2,1,0,4]],[@_[3,2,1,4,0]],[@_[3,2,4,0,1]],[@_[3,2,4,1,0]],
5062             [@_[3,4,0,1,2]],[@_[3,4,0,2,1]],[@_[3,4,1,0,2]],[@_[3,4,1,2,0]],[@_[3,4,2,0,1]],
5063             [@_[3,4,2,1,0]],[@_[4,0,1,2,3]],[@_[4,0,1,3,2]],[@_[4,0,2,1,3]],[@_[4,0,2,3,1]],
5064             [@_[4,0,3,1,2]],[@_[4,0,3,2,1]],[@_[4,1,0,2,3]],[@_[4,1,0,3,2]],[@_[4,1,2,0,3]],
5065             [@_[4,1,2,3,0]],[@_[4,1,3,0,2]],[@_[4,1,3,2,0]],[@_[4,2,0,1,3]],[@_[4,2,0,3,1]],
5066             [@_[4,2,1,0,3]],[@_[4,2,1,3,0]],[@_[4,2,3,0,1]],[@_[4,2,3,1,0]],[@_[4,3,0,1,2]],
5067             [@_[4,3,0,2,1]],[@_[4,3,1,0,2]],[@_[4,3,1,2,0]],[@_[4,3,2,0,1]],[@_[4,3,2,1,0]]) if @_==5;
5068              
5069 0         0 my(@r,@p,@c,@i,@n); @i=(0,@_); @p=@c=1..@_; @n=1..@_-1;
  0         0  
  0         0  
  0         0  
5070             PERM:
5071 0         0 while(1){
5072 0 0       0 if($code){if(defined wantarray){push(@r,&$code(@i[@p]))}else{&$code(@i[@p])}}else{push@r,[@i[@p]]}
  0 0       0  
  0         0  
  0         0  
  0         0  
5073 0 0       0 for my$i(@n){splice@p,$i,0,shift@p;next PERM if --$c[$i];$c[$i]=$i+1}
  0         0  
  0         0  
  0         0  
5074             return@r
5075 0         0 }
5076             }
5077              
5078             =head2 cart
5079              
5080             Cartesian product
5081              
5082             B
5083              
5084             Input: two or more arrayrefs with accordingly x, y, z and so on number of elements.
5085              
5086             Output: An array of x * y * z number of arrayrefs. The arrays being the cartesian product of the input arrays.
5087              
5088             It can be useful to think of this as joins in SQL. In C
5089             more tables behind C, but without any C condition to join the tables.
5090              
5091             B
5092              
5093             B
5094              
5095             - Either two or more arrayrefs with x, y, z and so on number of elements.
5096              
5097             - Or coderefs to subs containing condition checks. Somewhat like C conditions in SQL.
5098              
5099             B An array of x * y * z number of arrayrefs (the cartesian product)
5100             minus the ones that did not fulfill the condition(s).
5101              
5102             This of is as joins with one or more where conditions as coderefs.
5103              
5104             The coderef input arguments can be placed last or among the array refs
5105             to save both runtime and memory if the conditions depend on
5106             arrays further back.
5107              
5108             B
5109              
5110             for(cart(\@a1,\@a2,\@a3)){
5111             my($a1,$a2,$a3) = @$_;
5112             print "$a1,$a2,$a3\n";
5113             }
5114              
5115             Prints the same as this:
5116              
5117             for my $a1 (@a1){
5118             for my $a2 (@a2){
5119             for my $a3 (@a3){
5120             print "$a1,$a2,$a3\n";
5121             }
5122             }
5123             }
5124              
5125             B (with a condition: the sum of the first two should be dividable with 3)
5126              
5127             for( cart( \@a1, \@a2, sub{sum(@$_)%3==0}, \@a3 ) ) {
5128             my($a1,$a2,$a3)=@$_;
5129             print "$a1,$a2,$a3\n";
5130             }
5131              
5132             Prints the same as this:
5133              
5134             for my $a1 (@a1){
5135             for my $a2 (@a2){
5136             next if 0==($a1+$a2)%3;
5137             for my $a3 (@a3){
5138             print "$a1,$a2,$a3\n";
5139             }
5140             }
5141             }
5142              
5143             B
5144              
5145             my @a1 = (1,2);
5146             my @a2 = (10,20,30);
5147             my @a3 = (100,200,300,400);
5148              
5149             my $s = join"", map "*".join(",",@$_), cart(\@a1,\@a2,\@a3);
5150             ok( $s eq "*1,10,100*1,10,200*1,10,300*1,10,400*1,20,100*1,20,200"
5151             ."*1,20,300*1,20,400*1,30,100*1,30,200*1,30,300*1,30,400"
5152             ."*2,10,100*2,10,200*2,10,300*2,10,400*2,20,100*2,20,200"
5153             ."*2,20,300*2,20,400*2,30,100*2,30,200*2,30,300*2,30,400");
5154              
5155             $s=join"",map "*".join(",",@$_), cart(\@a1,\@a2,\@a3,sub{sum(@$_)%3==0});
5156             ok( $s eq "*1,10,100*1,10,400*1,20,300*1,30,200*2,10,300*2,20,200*2,30,100*2,30,400");
5157              
5158             B
5159              
5160             Returns hashrefs instead of arrayrefs:
5161              
5162             my @cards=cart( #5200 cards: 100 decks of 52 cards
5163             deck => [1..100],
5164             value => [qw/2 3 4 5 6 7 8 9 10 J Q K A/],
5165             col => [qw/heart diamond club star/],
5166             );
5167             for my $card ( mix(@cards) ) {
5168             print "From deck number $$card{deck} we got $$card{value} $$card{col}\n";
5169             }
5170              
5171             Note: using sub-ref filters do not work (yet) in hash-mode. Use grep on result instead.
5172              
5173             =cut
5174              
5175             sub cart {
5176 5     5 1 850 my @ars=@_;
5177 5 100       17 if(!ref($_[0])){ #if hash-mode detected
5178 1   33     2 my(@k,@v); push@k,shift@ars and push@v,shift@ars while @ars;
  1         13  
5179 1         7 return map{my%h;@h{@k}=@$_;\%h}cart(@v);
  24         26  
  24         68  
  24         44  
5180             }
5181 4         6 my @res=map[$_],@{shift@ars};
  4         20  
5182 4         9 for my $ar (@ars){
5183 9 100 50     26 @res=grep{&$ar(@$_)}@res and next if ref($ar) eq 'CODE';
  24         51  
5184 8         13 @res=map{my$r=$_;map{[@$r,$_]}@$ar}@res;
  34         38  
  34         49  
  120         257  
5185             }
5186 4         63 return @res;
5187             }
5188              
5189             sub cart_easy { #not tested/exported http://stackoverflow.com/questions/2457096/in-perl-how-can-i-get-the-cartesian-product-of-multiple-sets
5190 0     0 0 0 my $last = pop @_;
5191 0 0       0 @_ ? (map {my$left=$_; map [@$left, $_], @$last } cart_easy(@_) )
  0         0  
  0         0  
5192             : (map [$_], @$last);
5193             }
5194              
5195             =head2 reduce
5196              
5197             From: Why Functional Programming Matters: L
5198              
5199             L
5200              
5201             DON'T TRY THIS AT HOME, C PROGRAMMERS.
5202              
5203             sub reduce (&@) {
5204             my ($proc, $first, @rest) = @_;
5205             return $first if @rest == 0;
5206             local ($a, $b) = ($first, reduce($proc, @rest));
5207             return $proc->();
5208             }
5209              
5210             Many functions can then be implemented with very little code. Such as:
5211              
5212             sub mean { (reduce {$a + $b} @_) / @_ }
5213              
5214             =cut
5215              
5216             sub reduce (&@) {
5217 0     0 1 0 my ($proc, $first, @rest) = @_;
5218 0 0       0 return $first if @rest == 0;
5219 28     28   135865 no warnings;
  28         61  
  28         32373  
5220 0         0 local ($a, $b) = ($first, reduce($proc, @rest));
5221 0         0 return $proc->();
5222             }
5223              
5224              
5225             =head2 pivot
5226              
5227             Resembles the pivot table function in Excel.
5228              
5229             C is used to spread out a slim and long table to a visually improved layout.
5230              
5231             For instance spreading out the results of C-selects from SQL:
5232              
5233             pivot( arrayref, columnname1, columnname2, ...)
5234              
5235             pivot( ref_to_array_of_arrayrefs, @list_of_names_to_down_fields )
5236              
5237             The first argument is a ref to a two dimensional table.
5238              
5239             The rest of the arguments is a list which also signals the number of
5240             columns from left in each row that is ending up to the left of the
5241             data table, the rest ends up at the top and the last element of
5242             each row ends up as data.
5243              
5244             top1 top1 top1 top1
5245             left1 left2 left3 top2 top2 top2 top2
5246             ----- ----- ----- ---- ---- ---- ----
5247             data data data data
5248             data data data data
5249             data data data data
5250              
5251             Example:
5252              
5253             my @table=(
5254             ["1997","Gerd", "Weight", "Summer",66],
5255             ["1997","Gerd", "Height", "Summer",170],
5256             ["1997","Per", "Weight", "Summer",75],
5257             ["1997","Per", "Height", "Summer",182],
5258             ["1997","Hilde","Weight", "Summer",62],
5259             ["1997","Hilde","Height", "Summer",168],
5260             ["1997","Tone", "Weight", "Summer",70],
5261            
5262             ["1997","Gerd", "Weight", "Winter",64],
5263             ["1997","Gerd", "Height", "Winter",158],
5264             ["1997","Per", "Weight", "Winter",73],
5265             ["1997","Per", "Height", "Winter",180],
5266             ["1997","Hilde","Weight", "Winter",61],
5267             ["1997","Hilde","Height", "Winter",164],
5268             ["1997","Tone", "Weight", "Winter",69],
5269            
5270             ["1998","Gerd", "Weight", "Summer",64],
5271             ["1998","Gerd", "Height", "Summer",171],
5272             ["1998","Per", "Weight", "Summer",76],
5273             ["1998","Per", "Height", "Summer",182],
5274             ["1998","Hilde","Weight", "Summer",62],
5275             ["1998","Hilde","Height", "Summer",168],
5276             ["1998","Tone", "Weight", "Summer",70],
5277            
5278             ["1998","Gerd", "Weight", "Winter",64],
5279             ["1998","Gerd", "Height", "Winter",171],
5280             ["1998","Per", "Weight", "Winter",74],
5281             ["1998","Per", "Height", "Winter",183],
5282             ["1998","Hilde","Weight", "Winter",62],
5283             ["1998","Hilde","Height", "Winter",168],
5284             ["1998","Tone", "Weight", "Winter",71],
5285             );
5286              
5287             .
5288              
5289             my @reportA=pivot(\@table,"Year","Name");
5290             print "\n\nReport A\n\n".tablestring(\@reportA);
5291              
5292             Will print:
5293              
5294             Report A
5295            
5296             Year Name Height Height Weight Weight
5297             Summer Winter Summer Winter
5298             ---- ----- ------ ------ ------ ------
5299             1997 Gerd 170 158 66 64
5300             1997 Hilde 168 164 62 61
5301             1997 Per 182 180 75 73
5302             1997 Tone 70 69
5303             1998 Gerd 171 171 64 64
5304             1998 Hilde 168 168 62 62
5305             1998 Per 182 183 76 74
5306             1998 Tone 70 71
5307              
5308             .
5309              
5310             my @reportB=pivot([map{$_=[@$_[0,3,2,1,4]]}(@t=@table)],"Year","Season");
5311             print "\n\nReport B\n\n".tablestring(\@reportB);
5312              
5313             Will print:
5314              
5315             Report B
5316            
5317             Year Season Height Height Height Weight Weight Weight Weight
5318             Gerd Hilde Per Gerd Hilde Per Tone
5319             ---- ------ ------ ------ ----- ----- ------ ------ ------
5320             1997 Summer 170 168 182 66 62 75 70
5321             1997 Winter 158 164 180 64 61 73 69
5322             1998 Summer 171 168 182 64 62 76 70
5323             1998 Winter 171 168 183 64 62 74 71
5324              
5325             .
5326              
5327             my @reportC=pivot([map{$_=[@$_[1,2,0,3,4]]}(@t=@table)],"Name","Attributt");
5328             print "\n\nReport C\n\n".tablestring(\@reportC);
5329              
5330             Will print:
5331              
5332             Report C
5333            
5334             Name Attributt 1997 1997 1998 1998
5335             Summer Winter Summer Winter
5336             ----- --------- ------ ------ ------ ------
5337             Gerd Height 170 158 171 171
5338             Gerd Weight 66 64 64 64
5339             Hilde Height 168 164 168 168
5340             Hilde Weight 62 61 62 62
5341             Per Height 182 180 182 183
5342             Per Weight 75 73 76 74
5343             Tone Weight 70 69 70 71
5344              
5345             .
5346              
5347             my @reportD=pivot([map{$_=[@$_[1,2,0,3,4]]}(@t=@table)],"Name");
5348             print "\n\nReport D\n\n".tablestring(\@reportD);
5349              
5350             Will print:
5351              
5352             Report D
5353            
5354             Name Height Height Height Height Weight Weight Weight Weight
5355             1997 1997 1998 1998 1997 1997 1998 1998
5356             Summer Winter Summer Winter Summer Winter Summer Winter
5357             ----- ------ ------ ------ ------ ------ ------ ------ ------
5358             Gerd 170 158 171 171 66 64 64 64
5359             Hilde 168 164 168 168 62 61 62 62
5360             Per 182 180 182 183 75 73 76 74
5361             Tone 70 69 70 71
5362              
5363             Options:
5364              
5365             Options to sort differently and show sums and percents are available. (...MORE DOC ON THAT LATER...)
5366              
5367             See also L
5368              
5369             =cut
5370              
5371             sub pivot {
5372 4     4 1 11 my($tabref,@vertikalefelt)=@_;
5373 4 50       15 my %opt=ref($vertikalefelt[-1]) eq 'HASH' ? %{pop(@vertikalefelt)} : ();
  0         0  
5374 4 50       16 my $opt_sum=1 if $opt{sum};
5375 4 50 0     8 my $opt_pro=exists $opt{prosent}?$opt{prosent}||0:undef;
5376 4   50     23 my $sortsub = $opt{'sortsub'} || \&_sortsub;
5377 4   33     18 my $sortsub_bortover = $opt{'sortsub_bortover'} || $sortsub;
5378 4   33     29 my $sortsub_nedover = $opt{'sortsub_nedover'} || $sortsub;
5379             #print serialize(\%opt,'opt');
5380             #print serialize(\$opt_pro,'opt_pro');
5381 4         7 my $antned=0+@vertikalefelt;
5382 4         7 my $bakerst=-1+@{$$tabref[0]};
  4         10  
5383 4         5 my(%h,%feltfinnes,%sum);
5384             #print "Bakerst<$bakerst>\n";
5385 4         9 for(@$tabref){
5386 112         256 my $rad=join($;,@$_[0..($antned-1)]);
5387 112         222 my $felt=join($;,@$_[$antned..($bakerst-1)]);
5388 112         150 my $verdi=$$_[$bakerst];
5389 112 50       240 length($rad) or $rad=' ';
5390 112 50       185 length($felt) or $felt=' ';
5391 112         227 $h{$rad}{$felt}=$verdi;
5392 112         239 $h{$rad}{"%$felt"}=$verdi;
5393 112 50 33     411 if($opt_sum or defined $opt_pro){
5394 0         0 $h{$rad}{Sum}+=$verdi;
5395 0         0 $sum{$felt}+=$verdi;
5396 0         0 $sum{Sum}+=$verdi;
5397             }
5398 112         164 $feltfinnes{$felt}++;
5399 112 50       319 $feltfinnes{"%$felt"}++ if $opt_pro;
5400             }
5401 4         26 my @feltfinnes = sort $sortsub_bortover keys%feltfinnes;
5402 4 50       12 push @feltfinnes, "Sum" if $opt_sum;
5403 4         8 my @t=([@vertikalefelt,map{replace($_,$;,"\n")}@feltfinnes]);
  23         42  
5404             #print serialize(\@feltfinnes,'feltfinnes');
5405             #print serialize(\%h,'h');
5406             #print "H = ".join(", ",sort _sortsub keys%h)."\n";
5407 4         18 for my $rad (sort $sortsub_nedover keys(%h)){
5408             my @rad=(split($;,$rad),
5409             map{
5410 23 50 33     154 if(/^\%/ and defined $opt_pro){
  120         309  
5411 0         0 my $sum=$h{$rad}{Sum};
5412 0         0 my $verdi=$h{$rad}{$_};
5413 0 0       0 if($sum!=0){
5414 0 0       0 defined $verdi
5415             ?sprintf("%*.*f",3+1+$opt_pro,$opt_pro,100*$verdi/$sum)
5416             :$verdi;
5417             }
5418             else{
5419 0 0       0 $verdi!=0?"div0":$verdi;
5420             }
5421             }
5422             else{
5423 120         243 $h{$rad}{$_};
5424             }
5425             }
5426             @feltfinnes);
5427 23         84 push(@t,[@rad]);
5428             }
5429 4 50       12 push(@t,"-",["Sum",(map{""}(2..$antned)),map{print "<$_>\n";$sum{$_}}@feltfinnes]) if $opt_sum;
  0         0  
  0         0  
  0         0  
5430 4         53 return @t;
5431             }
5432              
5433             # default sortsub for pivot()
5434              
5435             sub _sortsub {
5436 28     28   160 no warnings;
  28         47  
  28         13139  
5437             #my $c=($a<=>$b)||($a cmp $b);
5438             #return $c if $c;
5439             #printf "%-30s %-30s ",replace($a,$;,','),replace($b,$;,',');
5440 72     72   489 my @a=split $;,$a;
5441 72         470 my @b=split $;,$b;
5442 72         172 for(0..$#a){
5443 110         232 my $c=$a[$_]<=>$b[$_];
5444 110 100 66     398 return $c if $c and "$a[$_]$b[$_]"!~/[iI][nN][fF]|þ/i; # inf(inity)
5445 96         125 $c=$a[$_]cmp$b[$_];
5446 96 100       274 return $c if $c;
5447             }
5448 0         0 return 0;
5449             }
5450              
5451             =head2 tablestring
5452              
5453             B a reference to an array of arrayrefs -- a two dimensional table of strings and numbers
5454              
5455             B a string containing the textual table -- a string of two or more lines
5456              
5457             The first arrayref in the list refers to a list of either column headings (scalar)
5458             or ... (...more later...)
5459              
5460             In this output table:
5461              
5462             - the columns will not be wider than necessary by its widest value (any -tags are removed in every internal width-calculation)
5463              
5464             - multi-lined cell values are handled also
5465              
5466             - and so are html-tags, if the output is to be used inside
-tags on a web page. 
5467              
5468             - columns with just numeric values are right justified (header row excepted)
5469              
5470             Example:
5471              
5472             print tablestring([
5473             [qw/AA BB CCCC/],
5474             [123,23,"d"],
5475             [12,23,34],
5476             [77,88,99],
5477             ["lin\nes",12,"asdff\nfdsa\naa"],[0,22,"adf"]
5478             ]);
5479              
5480             Prints this string of 11 lines:
5481              
5482             AA BB CCCC
5483             --- -- -----
5484             123 23 d
5485             12 23 34
5486             77 8 99
5487            
5488             lin 12 asdff
5489             es fdsa
5490             aa
5491            
5492             10 22 adf
5493              
5494             As you can see, rows containing multi-lined cells gets an empty line before and after the row to separate it more clearly.
5495              
5496             =cut
5497              
5498             sub tablestring {
5499 5     5 1 27 my $tab=shift;
5500 5 50       14 my %o=$_[0] ? %{shift()} : ();
  0         0  
5501 5         8 my $fjern_tom=$o{fjern_tomme_kolonner};
5502 5         8 my $ikke_space=$o{ikke_space};
5503 5   50     23 my $nodup=$o{nodup}||0;
5504 5         7 my $ikke_hodestrek=$o{ikke_hodestrek};
5505 5 50       13 my $pagesize=exists $o{pagesize} ? $o{pagesize}-3 : 9999999;
5506 5         6 my $venstretvang=$o{venstre};
5507 5         6 my(@bredde,@venstre,@hoeyde,@ikketom,@nodup);
5508 5         7 my $hode=1;
5509 5         8 my $i=0;
5510 5         8 my $j;
5511 5         11 for(@$tab){
5512 33         34 $j=0;
5513 33         43 $hoeyde[$i]=0;
5514 33         37 my $nodup_rad=$nodup;
5515 33 50       72 if(ref($_) eq 'ARRAY'){
5516 33         53 for(@$_){
5517 210         272 my $celle=$_;
5518 210   100     431 $bredde[$j]||=0;
5519 210 50 33     582 if($nodup_rad and $i>0 and $$tab[$i][$j] eq $$tab[$i-1][$j] || ($nodup_rad=0)){
      0        
      33        
5520 0 0       0 $celle=$nodup==1?"":$nodup;
5521 0         0 $nodup[$i][$j]=1;
5522             }
5523             else{
5524 210         213 my $hoeyde=0;
5525 210         201 my $bredere;
5526 28     28   1335 no warnings;
  28         1237  
  28         16611  
5527 210 100 100     799 $ikketom[$j]=1 if !$hode && length($celle)>0;
5528 210         445 for(split("\n",$celle)){
5529 236 50       411 $bredere=/
5530 236         277 s/<[^>]+>//g;
5531 236         239 $hoeyde++;
5532 236         265 s/>/>/g;
5533 236         258 s/</
5534 236 100       585 $bredde[$j]=length($_)+1+$bredere if length($_)+1+$bredere>$bredde[$j];
5535 236 100 100     1545 $venstre[$j]=1 if $_ && !/^\s*[\-\+]?(\d+|\d*\.\d+)\s*\%?$/ && !$hode;
      100        
5536             }
5537 210 100 66     614 if( $hoeyde>1 && !$ikke_space){
5538 25 100       53 $hoeyde++ unless $hode;
5539 25 100 100     69 $hoeyde[$i-1]++ if $i>1 && $hoeyde[$i-1]==1;
5540             }
5541 210 100       477 $hoeyde[$i]=$hoeyde if $hoeyde>$hoeyde[$i];
5542             }
5543 210         279 $j++;
5544             }
5545             }
5546             else{
5547 0         0 $hoeyde[$i]=1;
5548 0         0 $ikke_hodestrek=1;
5549             }
5550 33         37 $hode=0;
5551 33         50 $i++;
5552             }
5553 5         9 $i=$#hoeyde;
5554 5         7 $j=$#bredde;
5555 5 50 33     24 if($i==0 or $venstretvang) { @venstre=map{1}(0..$j) }
  0         0  
  0         0  
5556 5 50       11 else { for(0..$j){ $venstre[$_]=1 if !$ikketom[$_] } }
  33         68  
5557 5         8 my @tabut;
5558 5         5 my $rad_startlinje=0;
5559 5         8 my @overskrift;
5560             my $overskrift_forrige;
5561 5         8 for my $x (0..$i){
5562 33 50       88 if($$tab[$x] eq '-'){
5563 0 0       0 my @tegn=map {$$tab[$x-1][$_]=~/\S/?"-":" "} (0..$j);
  0         0  
5564 0         0 $tabut[$rad_startlinje]=join(" ",map {$tegn[$_] x ($bredde[$_]-1)} (0..$j));
  0         0  
5565             }
5566             else{
5567 33         54 for my $y (0..$j){
5568 210 50 33     464 next if $fjern_tom && !$ikketom[$y];
5569 28     28   1318 no warnings;
  28         49  
  28         22085  
5570            
5571 210 0 33     1343 my @celle=
    50          
5572             !$overskrift_forrige&&$nodup&&$nodup[$x][$y]
5573             ?($nodup>0?():((" " x (($bredde[$y]-length($nodup))/2)).$nodup))
5574             :split("\n",$$tab[$x][$y]);
5575 210         434 for(0..($hoeyde[$x]-1)){
5576 261         310 my $linje=$rad_startlinje+$_;
5577 261   100     606 my $txt=shift @celle || '';
5578 261 100 100     1489 $txt=sprintf("%*s",$bredde[$y]-1,$txt) if length($txt)>0 && !$venstre[$y] && ($x>0 || $ikke_hodestrek);
      66        
      66        
5579 261         374 $tabut[$linje].=$txt;
5580 261 100       431 if($y==$j){
5581 42         185 $tabut[$linje]=~s/\s+$//;
5582             }
5583             else{
5584 219         223 my $bredere;
5585 219 50       399 $bredere = $txt=~/
5586 219         275 $txt=~s/<[^>]+>//g;
5587 219         271 $txt=~s/>/>/g;
5588 219         245 $txt=~s/</
5589 219         591 $tabut[$linje].= ' ' x ($bredde[$y]-length($txt)-$bredere);
5590             }
5591             }
5592             }
5593             }
5594 33         45 $rad_startlinje+=$hoeyde[$x];
5595              
5596             #--lage streker?
5597 33 50       63 if(not $ikke_hodestrek){
5598 33 100 33     155 if($x==0){
    50 33        
      0        
5599 5         9 for my $y (0..$j){
5600 33 50 33     64 next if $fjern_tom && !$ikketom[$y];
5601 33         68 $tabut[$rad_startlinje].=('-' x ($bredde[$y]-1))." ";
5602             }
5603 5         8 $rad_startlinje++;
5604 5         15 @overskrift=("",@tabut);
5605             }
5606             elsif(
5607             $x%$pagesize==0 || $nodup>0&&!$nodup[$x+1][$nodup-1]
5608             and $x+1<@$tab
5609             and !$ikke_hodestrek
5610             )
5611             {
5612 0         0 push(@tabut,@overskrift);
5613 0         0 $rad_startlinje+=@overskrift;
5614 0         0 $overskrift_forrige=1;
5615             }
5616             else{
5617 28         52 $overskrift_forrige=0;
5618             }
5619             }
5620             }#for x
5621 5         56 return join("\n",@tabut)."\n";
5622             }
5623              
5624             =head2 serialize
5625              
5626             Returns a data structure as a string. See also C
5627             (serialize was created long time ago before Data::Dumper appeared on
5628             CPAN, before CPAN even...)
5629              
5630             B One to four arguments.
5631              
5632             First argument: A reference to the structure you want.
5633              
5634             Second argument: (optional) The name the structure will get in the output string.
5635             If second argument is missing or is undef or '', it will get no name in the output.
5636              
5637             Third argument: (optional) The string that is returned is also put
5638             into a created file with the name given in this argument. Putting a
5639             C<< > >> char in from of the filename will append that file
5640             instead. Use C<''> or C to not write to a file if you want to
5641             use a fourth argument.
5642              
5643             Fourth argument: (optional) A number signalling the depth on which newlines is used in the output.
5644             The default is infinite (some big number) so no extra newlines are output.
5645              
5646             B A string containing the perl-code definition that makes that data structure.
5647             The input reference (first input argument) can be to an array, hash or a string.
5648             Those can contain other refs and strings in a deep data structure.
5649              
5650             Limitations:
5651              
5652             - Code refs are not handled (just returns C)
5653              
5654             - Regex, class refs and circular recursive structures are also not handled.
5655              
5656             B
5657              
5658             $a = 'test';
5659             @b = (1,2,3);
5660             %c = (1=>2, 2=>3, 3=>5, 4=>7, 5=>11);
5661             %d = (1=>2, 2=>3, 3=>\5, 4=>7, 5=>11, 6=>[13,17,19,{1,2,3,'asdf\'\\\''}],7=>'x');
5662             print serialize(\$a,'a');
5663             print serialize(\@b,'tab');
5664             print serialize(\%c,'c');
5665             print serialize(\%d,'d');
5666             print serialize(\("test'n roll",'brb "brb"'));
5667             print serialize(\%d,'d',undef,1);
5668              
5669             Prints accordingly:
5670              
5671             $a='test';
5672             @tab=('1','2','3');
5673             %c=('1','2','2','3','3','5','4','7','5','11');
5674             %d=('1'=>'2','2'=>'3','3'=>\'5','4'=>'7','5'=>'11','6'=>['13','17','19',{'1'=>'2','3'=>'asdf\'\\\''}]);
5675             ('test\'n roll','brb "brb"');
5676             %d=('1'=>'2',
5677             '2'=>'3',
5678             '3'=>\'5',
5679             '4'=>'7',
5680             '5'=>'11',
5681             '6'=>['13','17','19',{'1'=>'2','3'=>'asdf\'\\\''}],
5682             '7'=>'x');
5683              
5684             Areas of use:
5685              
5686             - Debugging (first and foremost)
5687              
5688             - Storing arrays and hashes and data structures of those on file, database or sending them over the net
5689              
5690             - eval earlier stored string to get back the data structure
5691              
5692             Be aware of the security implications of Cing a perl code string
5693             stored somewhere that unauthorized users can change them! You are
5694             probably better of using L or L without
5695             enabling the CODE-options if you have such security issues.
5696             More on decompiling Perl-code: L or L.
5697              
5698             =head2 dserialize
5699              
5700             Debug-serialize, dumping data structures for you to look at.
5701              
5702             Same as C but the output is given a newline every 80th character.
5703             (Every 80th or whatever C<$Acme::Tools::Dserialize_width> contains)
5704              
5705             =cut
5706              
5707             our $Dserialize_width=80;
5708 0   0 0   0 sub _kallstack { my $tilbake=shift||0; my @c; my $ret; $ret.=serialize(\@c,"caller$tilbake") while @c=caller(++$tilbake); $ret }
  0         0  
  0         0  
  0         0  
5709 0     0 1 0 sub dserialize{join "\n",serialize(@_)=~/(.{1,$Dserialize_width})/gs}
5710             sub serialize {
5711 28     28   150 no warnings;
  28         48  
  28         127928  
5712 1127     1127 1 4775 my($r,$name,$filename,$level)=@_;
5713 1127   100     3033 my @r=(undef,undef,($level||0)-1);
5714 1127 50       2122 if($filename){
5715 0 0       0 open my $fh, '>', $filename or croak("FEIL: could not open file $filename\n" . _kallstack());
5716 0         0 my $ret=serialize($r,$name,undef,$level);
5717 0         0 print $fh "$ret\n1;\n";
5718 0         0 close($fh);
5719 0         0 return $ret;
5720             }
5721 1127 100       2884 if(ref($r) eq 'SCALAR'){
    100          
    100          
    100          
    50          
    0          
    0          
    0          
    0          
5722 903 50       1580 return "\$$name=".serialize($r,@r).";\n" if $name;
5723 903 100       1692 return "undef" unless defined $$r;
5724 899         1128 my $ret=$$r;
5725 899         1410 $ret=~s/\\/\\\\/g;
5726 899         1140 $ret=~s/\'/\\'/g;
5727 899         2785 return "'$ret'";
5728             }
5729             elsif(ref($r) eq 'ARRAY'){
5730 72 100       163 return "\@$name=".serialize($r,@r).";\n" if $name;
5731 70         99 my $ret="(";
5732 70         134 for(@$r){
5733 350         819 $ret.=serialize(\$_,@r).",";
5734 350 100       1019 $ret.="\n" if $level>=0;
5735             }
5736 70         237 $ret=~s/,$//;
5737 70         131 $ret.=")";
5738 70 50       144 $ret.=";\n" if $name;
5739 70         235 return $ret;
5740             }
5741             elsif(ref($r) eq 'HASH'){
5742 31 100       250 return "\%$name=".serialize($r,@r).";\n" if $name;
5743 21         37 my $ret="(";
5744 21         105 for(sort keys %$r){
5745 73         193 $ret.=serialize(\$_,@r)."=>".serialize(\$$r{$_},@r).",";
5746 73 50       234 $ret.="\n" if $level>=0;
5747             }
5748 21         84 $ret=~s/,$//;
5749 21         33 $ret.=")";
5750 21 50       55 $ret.=";\n" if $name;
5751 21         132 return $ret;
5752             }
5753             elsif(ref($$r) eq 'ARRAY'){
5754 48 50       92 return "\@$name=".serialize($r,@r).";\n" if $name;
5755 48         63 my $ret="[";
5756 48         89 for(@$$r){
5757 100         555 $ret.=serialize(\$_,@r).",";
5758 100 50 33     487 $ret.="\n" if !defined $level or $level>=0;
5759             }
5760 48         133 $ret=~s/,$//;
5761 48         67 $ret.="]";
5762 48 50       89 $ret.=";\n" if $name;
5763 48         132 return $ret;
5764             }
5765             elsif(ref($$r) eq 'HASH'){
5766 73 50       138 return "\%$name=".serialize($r,@r).";\n" if $name;
5767 73         107 my $ret="{";
5768 73         268 for(sort keys %$$r){
5769 214         412 $ret.=serialize(\$_,@r)."=>".serialize(\$$$r{$_},@r).",";
5770 214 50       598 $ret.="\n" if $level>=0;
5771             }
5772 73         211 $ret=~s/,$//;
5773 73         93 $ret.="}";
5774 73 50       133 $ret.=";\n" if $name;
5775 73         208 return $ret;
5776             }
5777             elsif(ref($$r) eq 'SCALAR'){
5778 0         0 return "\\".serialize($$r,@r);
5779             }
5780             elsif(ref($r) eq 'LVALUE'){
5781 0         0 my $s="$$r";
5782 0         0 return serialize(\$s,@r);
5783             }
5784             elsif(ref($$r) eq 'CODE'){
5785             #warn "Tried to serialize CODE";
5786 0         0 return 'sub{croak "Can not serialize CODE-references, see perhaps B::Deparse and Storable"}'
5787             }
5788             elsif(ref($$r) eq 'GLOB'){
5789 0         0 warn "Tried to serialize a GLOB";
5790 0         0 return '\*STDERR'
5791             }
5792             else{
5793 0         0 my $tilbake;
5794 0         0 my($pakke,$fil,$linje,$sub,$hasargs,$wantarray);
5795 0   0     0 ($pakke,$fil,$linje,$sub,$hasargs,$wantarray)=caller($tilbake++) until $sub ne 'serialize' || $tilbake>20;
5796 0         0 croak("serialize() argument should be reference!\n".
5797             "\$r=$r\n".
5798             "ref(\$r) = ".ref($r)."\n".
5799             "ref(\$\$r) = ".ref($$r)."\n".
5800             "kallstack:\n". _kallstack());
5801             }
5802             }
5803              
5804             =head2 srlz
5805              
5806             Synonym to L, but remove unnecessary single quote chars around
5807             C<< \w+ >>-keys and number values (except numbers with leading zeros). Example:
5808              
5809             serialize:
5810              
5811             %s=('action'=>{'del'=>'0','ins'=>'0','upd'=>'18'},'post'=>'1348','pre'=>'1348',
5812             'updcol'=>{'Laerestednr'=>'18','Studietypenr'=>'18','Undervisningssted'=>'7','Url'=>'11'},
5813             'where'=>'where 1=1');
5814              
5815             srlz:
5816              
5817             %s=(action=>{del=>0,ins=>0,upd=>18},post=>1348,pre=>1348,
5818             updcol=>{Laerestednr=>18,Studietypenr=>18,Undervisningssted=>7,Url=>11},
5819             where=>'where 1=1');
5820              
5821             Todo: update L to do the same, but in the right way. (For now
5822             srlz runs the string from serialize() through two C<< s/// >>, this will break
5823             in certain cases). L will be kept as a synonym (or the other way around).
5824              
5825             =cut
5826              
5827             sub srlz {
5828 0     0 1 0 my $s=serialize(@_);
5829 0         0 $s=~s,'(\w+)'=>,$1=>,g;
5830 0         0 $s=~s,=>'((0|[1-9]\d*)(\.\d+)?(e[-+]?\d+)?)',=>$1,gi; #ikke ledende null! hm
5831 0         0 $s;
5832             }
5833              
5834              
5835             =head2 sys
5836              
5837             Call instead of C if you want C (Carp::croak) when something fails.
5838              
5839             sub sys($){ my$s=shift; my$r=system($s); $r==0 or croak"ERROR: system($s)==$r ($!) ($?)" }
5840              
5841              
5842             =cut
5843              
5844 0 0   0 1 0 sub sys($){ my$s=shift; my$r=system($s); $r==0 or croak"ERROR: system($s)==$r ($!) ($?)" }
  0         0  
  0         0  
5845              
5846             =head2 recursed
5847              
5848             Returns true or false (actually 1 or 0) depending on whether the
5849             current sub has been called by itself or not.
5850              
5851             sub xyz
5852             {
5853             xyz() if not recursed;
5854              
5855             }
5856              
5857             =cut
5858              
5859 0 0   0 1 0 sub recursed {(caller(1))[3] eq (caller(2))[3]?1:0}
5860              
5861             =head2 ed
5862              
5863             String editor commands
5864              
5865             literals: a-z 0-9 space
5866             move cursor: FBAEPN MF MB ME
5867             delete: D Md
5868             up/low/camelcase word U L C
5869             backspace: -
5870             search: S
5871             return/enter: R
5872             meta/esc/alt: M
5873             shift: T
5874             cut to eol: K
5875             caps lock: C
5876             yank: Y
5877             start and end: < >
5878             macro start/end/play: { } !
5879             times for next cmd: M (i.e. M24a inserts 24 a's)
5880              
5881             (TODO: alfa...and more docs needed)
5882              
5883             =cut
5884              
5885             our $Edcursor;
5886             sub ed {
5887 18     18 1 4351 my($s,$cs,$p,$buf)=@_; #string, commands, point (or cursor)
5888 18 100       58 return $$s=ed($$s,$cs,$p,$buf) if ref($s);
5889 17         33 my($sh,$cl,$m,$t,@m)=(0,0,0,undef);
5890 17         37 while(length($cs)){
5891 121         148 my $n = 0;
5892 121 50       489 my $c = $cs=~s,^(M\d+|M.|""|".+?"|S.+?R|\\.|.),,s ? $1 : die;
5893 121   100     402 $p = curb($p||0,0,length($s));
5894 121 100       234 if(defined$t){$cs="".($c x $t).$cs;$t=undef;next}
  1         5  
  1         2  
  1         3  
5895 120     81   375 my $add=sub{substr($s,$p,0)=$_[0];$p+=length($_[0])};
  81         141  
  81         144  
5896 120 50       821 if ($c =~ /^([a-z0-9 ])/){ &$add($sh^$cl?uc($1):$1); $sh=0 }
  65 100       208  
  65 100       80  
    100          
    100          
    100          
    100          
    100          
    50          
    100          
    100          
    100          
    100          
    100          
    50          
    100          
    100          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    50          
5897 1         3 elsif($c =~ /^"(.+)"$/) { &$add($1) }
5898 1         4 elsif($c =~ /^\\(.)/) { &$add($1) }
5899 2 50       6 elsif($c =~ /^S(.+)R/) { my $i=index($s,$1,$p);$p=$i+length($1) if $i>=0 }
  2         8  
5900 1         3 elsif($c =~ /^M(\d+)/) { $t=$1; next }
  1         6  
5901 2         3 elsif($c eq 'F') { $p++ }
5902 1         2 elsif($c eq 'B') { $p-- }
5903 0   0     0 elsif($c eq 'A') { $p-- while $p>0 and substr($s,$p-1,2)!~/^\n/ }
5904 8 50       39 elsif($c eq 'E') { substr($s,$p)=~/(.*)/ and $p+=length($1) }
5905 4         5 elsif($c eq 'D') { substr($s,$p,1)='' }
5906 3 50       21 elsif($c eq 'MD'){ substr($s,$p)=~s/^(\W*\w+)// and $buf=$1 }
5907 3 50       17 elsif($c eq 'MF'){ substr($s,$p)=~/(\W*\w+)/ and $p+=length($1) }
5908 3 50       19 elsif($c eq 'MB'){ substr($s,0,$p)=~/(\w+\W*)$/ and $p-=length($1) }
5909 0 0       0 elsif($c eq '-') { substr($s,--$p,1)='' if $p }
5910 5 50       37 elsif($c eq 'M-'){ substr($s,0,$p)=~s/(\w+\W*)$// and $p-=length($buf=$1)}
5911 3 50       19 elsif($c eq 'K') { substr($s,$p)=~s/(\S.+|\s*?\n)// and $buf=$1 }
5912 12         26 elsif($c eq 'Y') { &$add($buf) }
5913 0         0 elsif($c eq 'U') { substr($s,$p)=~s/(\W*)(\w+)/$1\U$2\E/; $p+=length($1.$2) }
  0         0  
5914 0         0 elsif($c eq 'L') { substr($s,$p)=~s/(\W*)(\w+)/$1\L$2\E/; $p+=length($1.$2) }
  0         0  
5915 0         0 elsif($c eq 'C') { substr($s,$p)=~s/(\W*)(\w+)/$1\u\L$2\E/; $p+=length($1.$2) }
  0         0  
5916 0         0 elsif($c eq '<') { $p=0 }
5917 0         0 elsif($c eq '>') { $p=length($s) }
5918 0         0 elsif($c eq 'T') { $sh=1 }
5919 0         0 elsif($c eq 'C') { $cl^=1 }
5920 1         2 elsif($c eq '{') { $m=1; @m=() }
  1         2  
5921 1         2 elsif($c eq '}') { $m=0 }
5922 2 50 33     20 elsif($c eq '!') { $m||!@m and die"ed: no macro"; $cs=join("",@m).$cs }
  2         5  
5923 2         5 elsif($c eq '""'){ &$add('"') }
5924 0         0 else { croak "ed: Unknown cmd '$c'\n" }
5925 119 100 100     578 push @m, $c if $m and $c ne '{';
5926             #warn serialize([$c,$m,$cs],'d');
5927             }
5928 17         20 $Edcursor=$p;
5929 17         50 $s;
5930             }
5931              
5932              
5933             #todo: sub unbless eller sub damn
5934             #todo: ..se også: use Data::Structure::Util qw/unbless/;
5935             #todo: ...og: Acme::Damn sin damn()
5936             #todo? sub swap($$) http://www.idg.no/computerworld/article242008.ece
5937             #todo? catal
5938             #todo?
5939             #void quicksort(int t, int u) int i, m; if (t >= u) return; swap(t, randint(t, u)); m = t; for (i = t + 1; i <= u; i++) if (x[i] < x[t]) swap(++m, i); swap(t, m) quicksort(t, m-1); quicksort(m+1, u);
5940              
5941              
5942             =head1 JUST FOR FUN
5943              
5944             =head2 brainfu
5945              
5946             B one or two arguments
5947              
5948             First argument: a string, source code of the brainfu
5949             language. String containing the eight charachters + - < > [ ] . ,
5950             Every other char is ignored silently.
5951              
5952             Second argument: if the source code contains commas (,) the second
5953             argument is the input characters in a string.
5954              
5955             B The resulting output from the program.
5956              
5957             Example:
5958              
5959             print brainfu(<<""); #prints "Hallo Verden!\n"
5960             ++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>---.+++++++++++..+++.>++.<<++++++++++++++
5961             .>----------.+++++++++++++.--------------.+.+++++++++.>+.>.
5962              
5963             See L
5964              
5965             =head2 brainfu2perl
5966              
5967             Just as L but instead it return the perl code to which the
5968             brainfu code is translated. Just C<< eval() >> this perl code to run.
5969              
5970             Example:
5971              
5972             print brainfu2perl('>++++++++[<++++++++>-]<++++++++.>++++++[<++++++>-]<---.');
5973              
5974             Prints this string:
5975              
5976             my($c,$o,@b)=(0); sub out{$o.=chr($b[$c]) for 1..$_[0]||1}
5977             ++$c;++$b[$c];++$b[$c];++$b[$c];++$b[$c];++$b[$c];++$b[$c];++$b[$c];++$b[$c];
5978             while($b[$c]){--$c;++$b[$c];++$b[$c];++$b[$c];++$b[$c];++$b[$c];++$b[$c];++$b[$c];
5979             ++$b[$c];++$c;--$b[$c];}--$c;++$b[$c];++$b[$c];++$b[$c];++$b[$c];++$b[$c];++$b[$c];
5980             ++$b[$c];++$b[$c];out;++$c;++$b[$c];++$b[$c];++$b[$c];++$b[$c];++$b[$c];++$b[$c];
5981             while($b[$c]){--$c;++$b[$c];++$b[$c];++$b[$c];++$b[$c];++$b[$c];++$b[$c];++$c;--$b[$c];}
5982             --$c;--$b[$c];--$b[$c];--$b[$c];out;$o;
5983              
5984             =head2 brainfu2perl_optimized
5985              
5986             Just as L but optimizes the perl code. The same
5987             example as above with brainfu2perl_optimized returns this equivalent
5988             but shorter perl code:
5989              
5990             $b[++$c]+=8;while($b[$c]){$b[--$c]+=8;--$b[++$c]}$b[--$c]+=8;out;$b[++$c]+=6;
5991             while($b[$c]){$b[--$c]+=6;--$b[++$c]}$b[--$c]-=3;out;$o;
5992              
5993             =cut
5994              
5995 3     3 1 691 sub brainfu { eval(brainfu2perl(@_)) }
5996              
5997             sub brainfu2perl {
5998 6     6 1 21 my($bf,$inp)=@_;
5999 17         76 my $perl='my($c,$inp,$o,@b)=(0,\''.$inp.'\'); no warnings; sub out{$o.=chr($b[$c]) for 1..$_[0]||1}'."\n";
6000 3 100 66     22 $perl.='sub inp{$inp=~s/(.)//s and $b[$c]=ord($1)}'."\n" if $inp and $bf=~/,/;
6001 3 100       918 $perl.=join("",map/\+/?'++$b[$c];':/\-/?'--$b[$c];':/\[/?'while($b[$c]){':/\]/?'}':/>/?'++$c;':/
    100          
    100          
    100          
    100          
    100          
    100          
    100          
6002 3         309 $perl;
6003             }
6004              
6005             sub brainfu2perl_optimized {
6006 0     14 1 0 my $perl=brainfu2perl(@_);
6007 0         0 $perl=~s{(((\+|\-)\3\$b\[\$c\];){2,})}{ '$b[$c]'.$3.'='.(grep/b/,split//,$1).';' }gisex;
  0         0  
6008 0         0 1 while $perl=~s/\+\+\$c;\-\-\$c;//g + $perl=~s/\-\-\$c;\+\+\$c;//g;
6009 0         0 $perl=~s{((([\-\+])\3\$c;){2,})}{"\$c$3=".(grep/c/,split//,$1).';'}gisex;
  0         0  
6010 0 0       0 $perl=~s{((\+\+|\-\-)\$c;([^;{}]+;))}{my($o,$s)=($2,$3);$s=~s/\$c/$o\$c/?$s:$1}ge;
  0         0  
  0         0  
6011 0         0 $perl=~s/\$c(\-|\+)=(\d+);(\+\+|\-\-)\$b\[\$c\]/$3.'$b[$c'.$1.'='.$2.'];'/ge;
  0         0  
6012 0         0 $perl=~s{((out;){2,})}{'out('.(grep/o/,split//,$1).');'}ge;
  0         0  
6013 0         0 $perl=~s/;}/}/g;$perl=~s/;+/;/g;
  0         0  
6014 0         0 $perl;
6015             }
6016              
6017              
6018             =head1 BLOOM FILTER SUBROUTINES
6019              
6020             Bloom filters can be used to check whether an element (a string) is a
6021             member of a large set using much less memory or disk space than other
6022             data structures. Trading speed and accuracy for memory usage. While
6023             risking false positives, Bloom filters have a very strong space
6024             advantage over other data structures for representing sets.
6025              
6026             In the example below, a set of 100000 phone numbers (or any string of
6027             any length) can be "stored" in just 91230 bytes if you accept that you
6028             can only check the data structure for existence of a string and accept
6029             false positives with an error rate of 0.03 (that is three percent, error
6030             rates are given in numbers larger than 0 and smaller than 1).
6031              
6032             You can not retrieve the strings in the set without using "brute
6033             force" methods and even then you would get slightly more strings than
6034             you put in because of the error rate inaccuracy.
6035              
6036             Bloom Filters have many uses.
6037              
6038             See also: L
6039              
6040             See also: L
6041              
6042             =head2 bfinit
6043              
6044             Initialize a new Bloom Filter:
6045              
6046             my $bf = bfinit( error_rate=>0.01, capacity=>100000 );
6047              
6048             The same:
6049              
6050             my $bf = bfinit( 0.01, 100000 );
6051              
6052             since two arguments is interpreted as error_rate and capacity accordingly.
6053              
6054              
6055             =head2 bfadd
6056              
6057             bfadd($bf, $_) for @phone_numbers; # Adding strings one at a time
6058              
6059             bfadd($bf, @phone_numbers); # ...or all at once (faster)
6060              
6061             Returns 1 on success. Dies (croaks) if more strings than capacity is added.
6062              
6063             =head2 bfcheck
6064              
6065             my $phone_number="97713246";
6066             if ( bfcheck($bf, $phone_number) ) {
6067             print "Yes, $phone_number was PROBABLY added\n";
6068             }
6069             else{
6070             print "No, $phone_number was DEFINITELY NOT added\n";
6071             }
6072              
6073             Returns true if C<$phone_number> exists in C<@phone_numbers>.
6074              
6075             Returns false most of the times, but sometimes true*), if C<$phone_number> doesn't exists in C<@phone_numbers>.
6076              
6077             *) This is called a false positive.
6078              
6079             Checking more than one key:
6080              
6081             @bools = bfcheck($bf, @keys); # or ...
6082             @bools = bfcheck($bf, \@keys); # better, uses less memory if @keys is large
6083              
6084             Returns an array the same size as @keys where each element is true or false accordingly.
6085              
6086             =head2 bfgrep
6087              
6088             Same as C except it returns the keys that exists in the bloom filter
6089              
6090             @found = bfgrep($bf, @keys); # or ...
6091             @found = bfgrep($bf, \@keys); # better, uses less memory if @keys is large, or ...
6092             @found = grep bfcheck($bf,$_), @keys; # same but slower
6093              
6094             =head2 bfgrepnot
6095              
6096             Same as C except it returns the keys that do NOT exists in the bloom filter:
6097              
6098             @not_found = bfgrepnot($bf, @keys); # or ...
6099             @not_found = bfgrepnot($bf, \@keys); # better, uses less memory if @keys is large, or ...
6100             @not_found = grep !bfcheck($bf,$_), @keys); # same but slower
6101              
6102             =head2 bfdelete
6103              
6104             Deletes from a counting bloom filter.
6105              
6106             To enable deleting be sure to initialize the bloom filter with the
6107             numeric C argument. The number of bits could be 2 or 3*)
6108             for small filters with a small capacity (a small number of keys), but
6109             setting the number to 4 ensures that even very large filters with very
6110             small error rates would not overflow.
6111              
6112             *) Acme::Tools do not currently support C<< counting_bits => 3 >> so 4
6113             and 8 are the only practical alternatives where 8 is almost always overkill.
6114              
6115             my $bf=bfinit(
6116             error_rate => 0.001,
6117             capacity => 10000000,
6118             counting_bits => 4 # power of 2, that is 2, 4, 8, 16 or 32
6119             );
6120             bfadd( $bf, @unique_phone_numbers);
6121             bfdelete($bf, @unique_phone_numbers);
6122              
6123             Example: examine the frequency of the counters with 4 bit counters and 4 million keys:
6124              
6125             my $bf=bfinit( error_rate=>0.001, capacity=>4e6, counting_bits=>4 );
6126             bfadd($bf,[1e3*$_+1 .. 1e3*($_+1)]) for 0..4000-1; # adding 4 million keys one thousand at a time
6127             my %c; $c{vec($$bf{filter},$_,$$bf{counting_bits})}++ for 0..$$bf{filterlength}-1;
6128             printf "%8d counters = %d\n",$c{$_},$_ for sort{$a<=>$b}keys%c;
6129              
6130             The output:
6131              
6132             28689562 counters = 0
6133             19947673 counters = 1
6134             6941082 counters = 2
6135             1608250 counters = 3
6136             280107 counters = 4
6137             38859 counters = 5
6138             4533 counters = 6
6139             445 counters = 7
6140             46 counters = 8
6141             1 counters = 9
6142              
6143             Even after the error_rate is changed from 0.001 to a percent of that, 0.00001, the limit of 16 (4 bits) is still far away:
6144              
6145             47162242 counters = 0
6146             33457237 counters = 1
6147             11865217 counters = 2
6148             2804447 counters = 3
6149             497308 counters = 4
6150             70608 counters = 5
6151             8359 counters = 6
6152             858 counters = 7
6153             65 counters = 8
6154             4 counters = 9
6155              
6156             In algorithmic terms the number of bits needed is C. Thats why 4 bits (counters up
6157             to 15) is "always" good enough except for extremely large capasities or extremely small error rates.
6158             (Except when adding the same key many times, which should be avoided, and Acme::Tools::bfadd do not
6159             check for that, perhaps in future versions).
6160              
6161             Bloom filters of the counting type are not very space efficient: The tables above shows that 84%-85%
6162             of the counters are 0 or 1. This means most bits are zero-bits. This doesn't have to be a problem if
6163             a counting bloom filter is used to be sent over slow networks because they are very compressable by
6164             common compression tools like I or L and such.
6165              
6166             Deletion of non-existing keys makes C die (croak).
6167              
6168             =head2 bfdelete
6169              
6170             Deletes from a counting bloom filter:
6171              
6172             bfdelete($bf, @keys);
6173             bfdelete($bf, \@keys);
6174              
6175             Returns C<$bf> after deletion.
6176              
6177             Croaks (dies) on deleting a non-existing key or deleting from an previouly overflown counter in a counting bloom filter.
6178              
6179             =head2 bfaddbf
6180              
6181             Adds another bloom filter to a bloom filter.
6182              
6183             Bloom filters has the proberty that bit-wise I-ing the bit-filters
6184             of two filters with the same capacity and the same number and type of
6185             hash functions, adds the filters:
6186              
6187             my $bf1=bfinit(error_rate=>0.01,capacity=>$cap,keys=>[1..500]);
6188             my $bf2=bfinit(error_rate=>0.01,capacity=>$cap,keys=>[501..1000]);
6189              
6190             bfaddbf($bf1,$bf2);
6191              
6192             print "Yes!" if bfgrep($bf1, 1..1000) == 1000;
6193              
6194             Prints yes since C now returns an array of all the 1000 elements.
6195              
6196             Croaks if the filters are of different dimensions.
6197              
6198             Works for counting bloom filters as well (C<< counting_bits=>4 >> e.g.)
6199              
6200             =head2 bfsum
6201              
6202             Returns the number of 1's in the filter.
6203              
6204             my $percent=100*bfsum($bf)/$$bf{filterlength};
6205             printf "The filter is %.1f%% filled\n",$percent; #prints 50.0% or so if filled to capacity
6206              
6207             Sums the counters for counting bloom filters (much slower than for non counting).
6208              
6209             =head2 bfdimensions
6210              
6211             Input, two numeric arguments: Capacity and error_rate.
6212              
6213             Outputs an array of two numbers: m and k.
6214              
6215             m = - n * log(p) / log(2)**2 # n = capacity, m = bits in filter (divide by 8 to get bytes)
6216             k = log(1/p) / log(2) # p = error_rate, uses perls internal log() with base e (2.718)
6217              
6218             ...that is: m = the best number of bits in the filter and k = the best
6219             number of hash functions optimized for the given capacity (n) and
6220             error_rate (p). Note that k is a dependent only of the error_rate. At
6221             about two percent error rate the bloom filter needs just the same
6222             number of bytes as the number of keys.
6223              
6224             Storage (bytes):
6225             Capacity Error-rate Error-rate Error-rate Error-rate Error-rate Error-rate Error-rate Error-rate Error-rate Error-rate Error-rate Error-rate
6226             0.000000001 0.00000001 0.0000001 0.000001 0.00001 0.0001 0.001 0.01 0.02141585 0.1 0.5 0.99
6227             ------------- ----------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
6228             10 54.48 48.49 42.5 36.51 30.52 24.53 18.53 12.54 10.56 6.553 2.366 0.5886
6229             100 539.7 479.8 419.9 360 300.1 240.2 180.3 120.4 100.6 60.47 18.6 0.824
6230             1000 5392 4793 4194 3595 2996 2397 1798 1199 1001 599.6 180.9 3.177
6231             10000 5.392e+04 4.793e+04 4.194e+04 3.594e+04 2.995e+04 2.396e+04 1.797e+04 1.198e+04 1e+04 5991 1804 26.71
6232             100000 5.392e+05 4.793e+05 4.193e+05 3.594e+05 2.995e+05 2.396e+05 1.797e+05 1.198e+05 1e+05 5.991e+04 1.803e+04 262
6233             1000000 5.392e+06 4.793e+06 4.193e+06 3.594e+06 2.995e+06 2.396e+06 1.797e+06 1.198e+06 1e+06 5.991e+05 1.803e+05 2615
6234             10000000 5.392e+07 4.793e+07 4.193e+07 3.594e+07 2.995e+07 2.396e+07 1.797e+07 1.198e+07 1e+07 5.991e+06 1.803e+06 2.615e+04
6235             100000000 5.392e+08 4.793e+08 4.193e+08 3.594e+08 2.995e+08 2.396e+08 1.797e+08 1.198e+08 1e+08 5.991e+07 1.803e+07 2.615e+05
6236             1000000000 5.392e+09 4.793e+09 4.193e+09 3.594e+09 2.995e+09 2.396e+09 1.797e+09 1.198e+09 1e+09 5.991e+08 1.803e+08 2.615e+06
6237             10000000000 5.392e+10 4.793e+10 4.193e+10 3.594e+10 2.995e+10 2.396e+10 1.797e+10 1.198e+10 1e+10 5.991e+09 1.803e+09 2.615e+07
6238             100000000000 5.392e+11 4.793e+11 4.193e+11 3.594e+11 2.995e+11 2.396e+11 1.797e+11 1.198e+11 1e+11 5.991e+10 1.803e+10 2.615e+08
6239             1000000000000 5.392e+12 4.793e+12 4.193e+12 3.594e+12 2.995e+12 2.396e+12 1.797e+12 1.198e+12 1e+12 5.991e+11 1.803e+11 2.615e+09
6240              
6241             Error rate: 0.99 Hash functions: 1
6242             Error rate: 0.5 Hash functions: 1
6243             Error rate: 0.1 Hash functions: 3
6244             Error rate: 0.0214158522653385 Hash functions: 6
6245             Error rate: 0.01 Hash functions: 7
6246             Error rate: 0.001 Hash functions: 10
6247             Error rate: 0.0001 Hash functions: 13
6248             Error rate: 0.00001 Hash functions: 17
6249             Error rate: 0.000001 Hash functions: 20
6250             Error rate: 0.0000001 Hash functions: 23
6251             Error rate: 0.00000001 Hash functions: 27
6252             Error rate: 0.000000001 Hash functions: 30
6253              
6254             =head2 bfstore
6255              
6256             Storing and retrieving bloom filters to and from disk uses Ls C and C. This:
6257              
6258             bfstore($bf,'filename.bf');
6259              
6260             It the same as:
6261              
6262             use Storable qw(store retrieve);
6263             ...
6264             store($bf,'filename.bf');
6265              
6266             =head2 bfretrieve
6267              
6268             This:
6269              
6270             my $bf=bfretrieve('filename.bf');
6271              
6272             Or this:
6273              
6274             my $bf=bfinit('filename.bf');
6275              
6276             Is the same as:
6277              
6278             use Storable qw(store retrieve);
6279             my $bf=retrieve('filename.bf');
6280              
6281             =head2 bfclone
6282              
6283             Deep copies the bloom filter data structure. (Which btw is not very deep, two levels at most)
6284              
6285             This:
6286              
6287             my $bfc = bfclone($bf);
6288              
6289             Works just as:
6290              
6291             use Storable;
6292             my $bfc=Storable::dclone($bf);
6293              
6294             =head2 Object oriented interface to bloom filters
6295              
6296             use Acme::Tools;
6297             my $bf=new Acme::Tools::BloomFilter(0.1,1000); # the same as bfinit, see bfinit above
6298             print ref($bf),"\n"; # prints Acme::Tools::BloomFilter
6299             $bf->add(@keys);
6300             $bf->check($keys[0]) and print "ok\n"; # prints ok
6301             $bf->grep(\@keys)==@keys and print "ok\n"; # prints ok
6302             $bf->store('filename.bf');
6303             my $bf2=bfretrieve('filename.bf');
6304             $bf2->check($keys[0]) and print "ok\n"; # still ok
6305              
6306             $bf2=$bf->clone();
6307              
6308             To instantiate a previously stored bloom filter:
6309              
6310             my $bf = Acme::Tools::BloomFilter->new( '/path/to/stored/bloomfilter.bf' );
6311              
6312             The o.o. interface has the same methods as the C-subs without the
6313             C-prefix in the names. The C is not available as a
6314             method, although C, C and
6315             C are synonyms.
6316              
6317             =head2 Internals and speed
6318              
6319             The internal hash-functions are C<< md5( "$key$salt" ) >> from L.
6320              
6321             Since C returns 128 bits and most medium to large sized bloom
6322             filters need only a 32 bit hash function, the result from md5() are
6323             split (C-ed) into 4 parts 32 bits each and are treated as if 4
6324             hash functions was called at once (speedup). Using different salts to
6325             the key on each md5 results in different hash functions.
6326              
6327             Digest::SHA512 would have been even better since it returns more bits,
6328             if it werent for the fact that it's much slower than Digest::MD5.
6329              
6330             String::CRC32::crc32 is faster than Digest::MD5, but not 4 times faster:
6331              
6332             time perl -e'use Digest::MD5 qw(md5);md5("asdf$_") for 1..10e6' #5.56 sec
6333             time perl -e'use String::CRC32;crc32("asdf$_") for 1..10e6' #2.79 sec, faster but not per bit
6334             time perl -e'use Digest::SHA qw(sha512);sha512("asdf$_") for 1..10e6' #36.10 sec, too slow (sha1, sha224, sha256 and sha384 too)
6335              
6336             Md5 seems to be an ok choice both for speed and avoiding collitions due to skewed data keys.
6337              
6338             =head2 Theory and math behind bloom filters
6339              
6340             L
6341              
6342             L
6343              
6344             L
6345              
6346             See also Scaleable Bloom Filters: L (not implemented in Acme::Tools)
6347              
6348             ...and perhaps L
6349              
6350             =cut
6351              
6352             sub bfinit {
6353 24 100   24 1 15650 return bfretrieve(@_) if @_==1;
6354 23 50 66     118 return bfinit(error_rate=>$_[0], capacity=>$_[1]) if @_==2 and 0<$_[0] and $_[0]<1 and $_[1]>1;
      66        
      33        
6355 21 0 33     61 return bfinit(error_rate=>$_[1], capacity=>$_[0]) if @_==2 and 0<$_[1] and $_[1]<1 and $_[0]>1;
      33        
      0        
6356 21         129 require Digest::MD5;
6357 21 50       54 @_%2&&croak "Arguments should be a hash of equal number of keys and values";
6358 21         85 my %arg=@_;
6359 21         69 my @ok_param=qw/error_rate capacity min_hashfuncs max_hashfuncs hashfuncs counting_bits adaptive keys/;
6360 21         84 my @not_ok=sort(grep!in($_,@ok_param),keys%arg);
6361 21 100       271 croak "Not ok param to bfinit: ".join(", ",@not_ok) if @not_ok;
6362 20 50 66     98 croak "Not an arrayref in keys-param" if exists $arg{keys} and ref($arg{keys}) ne 'ARRAY';
6363 20 50       77 croak "Not implemented counting_bits=$arg{counting_bits}, should be 2, 4, 8, 16 or 32" if !in(nvl($arg{counting_bits},1),1,2,4,8,16,32);
6364 20 50 33     73 croak "An bloom filters here can not be in both adaptive and counting_bits modes" if $arg{adaptive} and $arg{counting_bits}>1;
6365 20         176 my $bf={error_rate => 0.001, #default p
6366             capacity => 100000, #default n
6367             min_hashfuncs => 1,
6368             max_hashfuncs => 100,
6369             counting_bits => 1, #default: not counting filter
6370             adaptive => 0,
6371             %arg, #arguments
6372             key_count => 0,
6373             overflow => {},
6374             version => $Acme::Tools::VERSION,
6375             };
6376 20 100 100     384 croak "Error rate ($$bf{error_rate}) should be larger than 0 and smaller than 1" if $$bf{error_rate}<=0 or $$bf{error_rate}>=1;
6377 18 50       46 @$bf{'min_hashfuncs','max_hashfuncs'}=(map$arg{hashfuncs},1..2) if $arg{hashfuncs};
6378 18         53 @$bf{'filterlength','hashfuncs'}=bfdimensions($bf); #m and k
6379 18         776 $$bf{filter}=pack("b*", '0' x ($$bf{filterlength}*$$bf{counting_bits}) ); #hm x new empty filter
6380             $$bf{unpack}= $$bf{filterlength}<=2**16/4 ? "n*" # /4 alleviates skewing if m just slightly < 2**x
6381 18 50       57 :$$bf{filterlength}<=2**32/4 ? "N*"
    100          
6382             : "Q*";
6383 18 100       48 bfadd($bf,@{$arg{keys}}) if $arg{keys};
  8         78  
6384 16         95 return $bf;
6385             }
6386             sub bfaddbf {
6387 2     2 1 5 my($bf,$bf2)=@_;
6388             my $differror=join"\n",
6389             map "Property $_ differs ($$bf{$_} vs $$bf2{$_})",
6390 2         42 grep $$bf{$_} ne $$bf2{$_},
6391             qw/capacity counting_bits adaptive hashfuncs filterlength/; #not error_rate
6392 2 50       8 croak $differror if $differror;
6393 2 50       9 croak "Can not add adaptive bloom filters" if $$bf{adaptive};
6394 2         5 my $count=$$bf{key_count}+$$bf2{key_count};
6395             croak "Exceeded filter capacity $$bf{key_count} + $$bf2{key_count} = $count > $$bf{capacity}"
6396 2 50       10 if $count > $$bf{capacity};
6397 2         7 $$bf{key_count}+=$$bf2{key_count};
6398 2 100       8 if($$bf{counting_bits}==1){
6399 1         5 $$bf{filter} |= $$bf2{filter};
6400             #$$bf{filter} = $$bf{filter} | $$bf2{filter}; #or-ing
6401             }
6402             else {
6403 1         4 my $cb=$$bf{counting_bits};
6404 1         6 for(0..$$bf{filterlength}-1){
6405             my $sum=
6406             vec($$bf{filter}, $_,$cb)+
6407 4793         8390 vec($$bf2{filter},$_,$cb);
6408 4793 50       9761 if( $sum>2**$cb-1 ){
6409 0         0 $sum=2**$cb-1;
6410 0         0 $$bf{overflow}{$_}++;
6411             }
6412 4793         9283 vec($$bf{filter}, $_,$cb)=$sum;
6413 28     28   187 no warnings;
  28         49  
  28         91601  
6414             $$bf{overflow}{$_}+=$$bf2{overflow}{$_}
6415 0         0 and keys(%{$$bf{overflow}})>10 #hmm, arbitrary limit
6416             and croak "Too many overflows, concider doubling counting_bits from $cb to ".(2*$cb)
6417 4793 50 0     13225 if exists $$bf2{overflow}{$_};
      0        
6418             }
6419             }
6420 2         7 return $bf; #for convenience
6421             }
6422             sub bfsum {
6423 8     8 1 40 my($bf)=@_;
6424 8 100       89 return unpack( "%32b*", $$bf{filter}) if $$bf{counting_bits}==1;
6425 3         8 my($sum,$cb)=(0,$$bf{counting_bits});
6426 3         5708 $sum+=vec($$bf{filter},$_,$cb) for 0..$$bf{filterlength}-1;
6427 3         23 return $sum;
6428             }
6429             sub bfadd {
6430 11     11 1 2573 require Digest::MD5;
6431 11         876 my($bf,@keys)=@_;
6432 11 50       34 return if !@keys;
6433 11 100 66     45 my $keysref=@keys==1 && ref($keys[0]) eq 'ARRAY' ? $keys[0] : \@keys;
6434 11         51 my($m,$k,$up,$n,$cb,$adaptive)=@$bf{'filterlength','hashfuncs','unpack','capacity','counting_bits','adaptive'};
6435 11         37 for(@$keysref){
6436             #croak "Key should be scalar" if ref($_);
6437 15084 50 66     40952 $$bf{key_count} >= $n and croak "Exceeded filter capacity $n" or $$bf{key_count}++;
6438 15083         18626 my @h; push @h, unpack $up, Digest::MD5::md5($_,0+@h) while @h<$k;
  15083         132284  
6439 15083 100 66     51645 if ($cb==1 and !$adaptive) { # normal bloom filter
    50          
    0          
6440 11110         102943 vec($$bf{filter}, $h[$_] % $m, 1) = 1 for 0..$k-1;
6441             }
6442             elsif ($cb>1) { # counting bloom filter
6443 3973         7256 for(0..$k-1){
6444 11919         17176 my $pos=$h[$_] % $m;
6445             my $c=
6446             vec($$bf{filter}, $pos, $cb) =
6447 11919         29225 vec($$bf{filter}, $pos, $cb) + 1;
6448 11919 100       35642 if($c==0){
6449 26         51 vec($$bf{filter}, $pos, $cb) = -1;
6450             $$bf{overflow}{$pos}++
6451 26 100 100     134 and keys(%{$$bf{overflow}})>10 #hmm, arbitrary limit
  2         244  
6452             and croak "Too many overflows, concider doubling counting_bits from $cb to ".(2*$cb);
6453             }
6454             }
6455             }
6456             elsif ($adaptive) { # adaptive bloom filter
6457 0         0 my($i,$key,$bit)=(0+@h,$_);
6458 0         0 for(0..$$bf{filterlength}-1){
6459 0 0       0 $i+=push(@h, unpack $up, Digest::MD5::md5($key,$i)) if !@h;
6460 0         0 my $pos=shift(@h) % $m;
6461 0         0 $bit=vec($$bf{filter}, $pos, 1);
6462 0         0 vec($$bf{filter}, $pos, 1)=1;
6463 0 0 0     0 last if $_>=$k-1 and $bit==0;
6464             }
6465             }
6466 0         0 else {croak}
6467             }
6468 9         733 return 1;
6469             }
6470             sub bfcheck {
6471 5     5 1 83 require Digest::MD5;
6472 5         1178 my($bf,@keys)=@_;
6473 5 50       18 return if !@keys;
6474 5 50 33     26 my $keysref=@keys==1 && ref($keys[0]) eq 'ARRAY' ? $keys[0] : \@keys;
6475 5         24 my($m,$k,$up,$cb,$adaptive)=@$bf{'filterlength','hashfuncs','unpack','counting_bits','adaptive'};
6476 5         12 my $wa=wantarray();
6477 5 50       15 if(!$adaptive){ # normal bloom filter or counting bloom filter
6478             return map {
6479 5         65 my $match = 1; # match if every bit is on
  24001         28811  
6480 24001         28750 my @h; push @h, unpack $up, Digest::MD5::md5($_,0+@h) while @h<$k;
  24001         222331  
6481 24001   100     209677 vec($$bf{filter}, $h[$_] % $m, $cb) or $match=0 or last for 0..$k-1;
      100        
6482 24001 50       44673 return $match if !$wa;
6483 24001         51962 $match;
6484             } @$keysref;
6485             }
6486             else { # adaptive bloom filter
6487             return map {
6488 0         0 my($match,$i,$key,$bit,@h)=(1,0,$_);
  0         0  
6489 0         0 for(0..$$bf{filterlength}-1){
6490 0 0       0 $i+=push(@h, unpack $up, Digest::MD5::md5($key,$i)) if !@h;
6491 0         0 my $pos=shift(@h) % $m;
6492 0         0 $bit=vec($$bf{filter}, $pos, 1);
6493 0 0 0     0 $match++ if $_ > $k-1 and $bit==1;
6494 0 0 0     0 $match=0 if $_ <= $k-1 and $bit==0;
6495 0 0       0 last if $bit==0;
6496             }
6497 0 0       0 return $match if !$wa;
6498 0         0 $match;
6499             } @$keysref;
6500             }
6501             }
6502             sub bfgrep { # just a copy of bfcheck with map replaced by grep
6503 8     8 1 870 require Digest::MD5;
6504 8         24 my($bf,@keys)=@_;
6505 8 50       27 return if !@keys;
6506 8 50 33     65 my $keysref=@keys==1 && ref($keys[0]) eq 'ARRAY' ? $keys[0] : \@keys;
6507 8         34 my($m,$k,$up,$cb)=@$bf{'filterlength','hashfuncs','unpack','counting_bits'};
6508             return grep {
6509 8         29 my $match = 1; # match if every bit is on
  6100         7316  
6510 6100         6722 my @h; push @h, unpack $up, Digest::MD5::md5($_,0+@h) while @h<$k;
  6100         40807  
6511 6100   100     42786 vec($$bf{filter}, $h[$_] % $m, $cb) or $match=0 or last for 0..$k-1;
      100        
6512 6100         11486 $match;
6513             } @$keysref;
6514             }
6515             sub bfgrepnot { # just a copy of bfgrep with $match replaced by not $match
6516 1     1 1 9 require Digest::MD5;
6517 1         3 my($bf,@keys)=@_;
6518 1 50       5 return if !@keys;
6519 1 50 33     16 my $keysref=@keys==1 && ref($keys[0]) eq 'ARRAY' ? $keys[0] : \@keys;
6520 1         5 my($m,$k,$up,$cb)=@$bf{'filterlength','hashfuncs','unpack','counting_bits'};
6521             return grep {
6522 1         5 my $match = 1; # match if every bit is on
  1000         1246  
6523 1000         1149 my @h; push @h, unpack $up, Digest::MD5::md5($_,0+@h) while @h<$k;
  1000         6814  
6524 1000   50     7027 vec($$bf{filter}, $h[$_] % $m, $cb) or $match=0 or last for 0..$k-1;
      50        
6525 1000         2346 !$match;
6526             } @$keysref;
6527             }
6528             sub bfdelete {
6529 3     3 1 91 require Digest::MD5;
6530 3         17 my($bf,@keys)=@_;
6531 3 50       12 return if !@keys;
6532 3 100 100     20 my $keysref=@keys==1 && ref($keys[0]) eq 'ARRAY' ? $keys[0] : \@keys;
6533 3         11 my($m,$k,$up,$cb)=@$bf{'filterlength','hashfuncs','unpack','counting_bits'};
6534 3 50       8 croak "Cannot delete from non-counting bloom filter (use counting_bits 4 e.g.)" if $cb==1;
6535 3         7 for my $key (@$keysref){
6536 501         537 my @h; push @h, unpack $up, Digest::MD5::md5($key,0+@h) while @h<$k;
  501         3437  
6537 501 50 33     1432 $$bf{key_count}==0 and croak "Deleted all and then some" or $$bf{key_count}--;
6538 501         782 my($ones,$croak,@pos)=(0);
6539 501         925 for(0..$k-1){
6540 1503         2149 my $pos=$h[$_] % $m;
6541             my $c=
6542 1503         2267 vec($$bf{filter}, $pos, $cb);
6543 1503         3127 vec($$bf{filter}, $pos, $cb)=$c-1;
6544 1503 100       3244 $croak="Cannot delete a non-existing key $key" if $c==0;
6545             $croak="Cannot delete with previously overflown position. Try doubleing counting_bits"
6546 1503 50 66     6247 if $c==1 and ++$ones and $$bf{overflow}{$pos};
      66        
6547             }
6548 501 100       1241 if($croak){ #rollback
6549             vec($$bf{filter}, $h[$_] % $m, $cb)=
6550 1         11 vec($$bf{filter}, $h[$_] % $m, $cb)+1 for 0..$k-1;
6551 1         200 croak $croak;
6552             }
6553             }
6554 2         20 return $bf;
6555             }
6556             sub bfstore {
6557 1     1 1 22727 require Storable;
6558 1         8 Storable::store(@_);
6559             }
6560             sub bfretrieve {
6561 2     2 1 527 require Storable;
6562 2         11 my $bf=Storable::retrieve(@_);
6563 2 50       545 carp "Retrieved bloom filter was stored in version $$bf{version}, this is version $VERSION" if $$bf{version}>$VERSION;
6564 2         7 return $bf;
6565             }
6566             sub bfclone {
6567 1     1 1 30668 require Storable;
6568 1         8452 return Storable::dclone(@_); #could be faster
6569             }
6570             sub bfdimensions_old {
6571             my($n,$p,$mink,$maxk, $k,$flen,$m)=
6572 0 0   0 0 0 @_==1 ? (@{$_[0]}{'capacity','error_rate','min_hashfuncs','max_hashfuncs'},1)
  0 0       0  
6573             :@_==2 ? (@_,1,100,1)
6574             : croak "Wrong number of arguments (".@_."), should be 2";
6575 0 0 0     0 croak "p ($p) should be > 0 and < 1" if not ( 0<$p && $p<1 );
6576 0   0     0 $m=-1*$_*$n/log(1-$p**(1/$_)) and (!defined $flen or $m<$flen) and ($flen,$k)=($m,$_) for $mink..$maxk;
      0        
      0        
6577 0         0 $flen = int(1+$flen);
6578 0         0 return ($flen,$k);
6579             }
6580             sub bfdimensions {
6581             my($n,$p,$mink,$maxk)=
6582 18 0   18 1 48 @_==1 ? (@{$_[0]}{'capacity','error_rate','min_hashfuncs','max_hashfuncs'})
  18 50       52  
6583             :@_==2 ? (@_,1,100)
6584             : croak "Wrong number of arguments (".@_."), should be 2";
6585 18         66 my $k=log(1/$p)/log(2); # k hash funcs
6586 18         47 my $m=-$n*log($p)/log(2)**2; # m bits in filter
6587 18         65 return ($m+0.5,min($maxk,max($mink,int($k+0.5))));
6588             }
6589              
6590             #crontab -e
6591             #01 4,10,16,22 * * * /usr/bin/perl -MAcme::Tools -e'Acme::Tools::_update_currency_file("/var/www/html/currency-rates")' > /dev/null 2>&1
6592              
6593             sub _update_currency_file { #call from cron
6594 0   0 0   0 my $fn=shift()||'/var/www/html/currency-rates';
6595 0   0     0 my %exe=map+($_=>"/usr/bin/$_"),qw/curl ci/;-x$_ or die for values %exe;
  0         0  
6596 0 0       0 open my $F, '>', $fn or die"ERROR: Could not write file $fn ($!)\n";
6597 0         0 print $F "#-- Currency rates ".localtime()." (".time().")\n";
6598 0         0 print $F "# File generated by Acme::Tools version $VERSION\n";
6599 0         0 print $F "# Updated every 6th hour on http://calthis.com/currency-rates\n";
6600 0         0 print $F "NOK 1.000000000\n";
6601 0         0 my $amount=1000;
6602 0         0 my $data=qx($exe{curl} -s "http://www.x-rates.com/table/?from=NOK&amount=$amount");
6603 0         0 $data=~s,to=([A-Z]{3})(.)>,$2>$1,g;
6604 0         0 my @data=ht2t($data,"Alphabetical order"); shift @data;
  0         0  
6605 0 0       0 @data=map "$$_[1] ".($$_[4]>1e-2?$$_[4]:$$_[2]?sprintf("%.8f",$amount/$$_[2]):0)."\n",@data;
    0          
6606 0         0 my %data=map split,@data;
6607 0         0 my@tc=qx($exe{curl} -s https://btc-e.com/api/3/ticker/btc_usd-ltc_usd)=~/avg.?:(\d+\.?\d*)/g;
6608 0         0 push @data,"BTC ".($tc[0]*$data{USD})."\n";
6609 0         0 push @data,"LTC ".($tc[1]*$data{USD})."\n";
6610 0         0 print $F sort(@data);
6611 0         0 close($F);
6612 0 0       0 qx($exe{ci} -l -m. -d $fn) if -w"$fn,v";
6613             }
6614              
6615             sub ftype {
6616 0     0 0 0 my $f=shift;
6617 0 0 0     0 -e $f and
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
6618             -f$f ? 'file' # -f File is a plain file.
6619             :-d$f ? 'dir' # -d File is a directory.
6620             :-l$f ? 'symlink' # -l File is a symbolic link.
6621             :-p$f ? 'pipe' # -p File is a named pipe (FIFO), or Filehandle is a pipe.
6622             :-S$f ? 'socket' # -S File is a socket.
6623             :-b$f ? 'blockfile' # -b File is a block special file.
6624             :-c$f ? 'charfile' # -c File is a character special file.
6625             :-t$f ? 'ttyfile' # -t Filehandle is opened to a tty.
6626             : ''
6627             or undef;
6628             }
6629              
6630             =head1 COMMANDS
6631              
6632             =head2 install_acme_command_tools
6633              
6634             sudo perl -MAcme::Tools -e install_acme_command_tools
6635             Wrote executable /usr/local/bin/conv
6636             Wrote executable /usr/local/bin/due
6637             Wrote executable /usr/local/bin/xcat
6638             Wrote executable /usr/local/bin/freq
6639             Wrote executable /usr/local/bin/deldup
6640             Wrote executable /usr/local/bin/wipe
6641              
6642             Examples of commands then made available:
6643              
6644             conv 1 USD EUR #might show 0.88029 if thats the current currency rate. Uses conv()
6645             conv .5 in cm #reveals that 1/2 inch is 1.27 cm, see doc on conv() for all supported units
6646             due [-h] /path/1/ /path/2/ #like du, but show statistics on file extentions instead of subdirs
6647             xcat file #like cat, zcat, bzcat or xzcat in one. Uses file extention to decide. Uses openstr()
6648             freq file #reads file(s) or stdin and view counts of each byte 0-255
6649             deldup [-d] path1/ path2/ #reports (and optionally deletes) duplicate files NOT IMPLEMENTED YET!
6650             ccmd grep string /huge/file #caches stdout+stderr for 15 minutes (default) for much faster results later
6651             ccmd "sleep 2;echo hello" #slow first time. Note the quotes!
6652             ccmd "du -s ~/*|sort -n|tail" #ccmd store stdout+stderr in /tmp files (default)
6653              
6654             =head3 due
6655              
6656             Like C command but views space used by file extentions instead of dirs. Options:
6657              
6658             due [-options] [dirs] [files]
6659             due -h View bytes "human readable", i.e. C<8.72 MB> instead of C<9145662 b> (bytes)
6660             due -k | -m View bytes in kilobytes | megabytes (1024 | 1048576)
6661             due -K Like -k but uses 1000 instead of 1024
6662             due -z View two extentions if .z .Z .gz .bz2 .rz or .xz (.tar.gz, not just .gz)
6663             due -M Also show min, medium and max date (mtime) of files, give an idea of their age
6664             due -P Also show 10, 50 (medium) and 90 percentile of file date
6665             due -MP Both -M and -P, shows min, 10p, 50p, 90p and max
6666             due -a Sort output alphabetically by extention (default order is by size)
6667             due -c Sort output by number of files
6668             due -i Ignore case, .GZ and .gz is the same, output in lower case
6669             due -t Adds time of day to -M and -P output
6670             due -e 'regex' Exclude files (full path) matching regex. Ex: due -e '\.git'
6671              
6672             =cut
6673              
6674             sub install_acme_command_tools {
6675 0     0 1 0 my $dir=(grep -d$_, @_, '/usr/local/bin', '/usr/bin')[0];
6676 0         0 for(qw( conv due xcat freq deldup ccmd )){
6677 0         0 unlink("$dir/$_");
6678 0         0 writefile("$dir/$_", "#!$^X\nuse Acme::Tools;\nAcme::Tools::cmd_$_(\@ARGV);\n");
6679 0         0 sys("/bin/chmod +x $dir/$_");
6680 0         0 print "Wrote executable $dir/$_\n";
6681             }
6682             }
6683 0     0 0 0 sub cmd_conv { print conv(@ARGV)."\n" }
6684 28     28   51697 use Data::Dumper;
  28         294442  
  28         3305  
6685             sub cmd_due { #TODO: output from tar tvf and ls and find -ls
6686 0     0 0 0 require Getopt::Std; my %o; Getopt::Std::getopts("zkKmhciMPate:" => \%o);
  0         0  
  0         0  
6687 0         0 require File::Find;
6688 28     28   189 no warnings 'uninitialized';
  28         55  
  28         86776  
6689 0 0       0 die"$0: -h, -k or -m can not be used together\n" if $o{h}+$o{k}+$o{m}>1;
6690 0 0       0 die"$0: -c and -a can not be used together\n" if $o{a}+$o{c}>1;
6691 0 0       0 die"$0: -k and -m can not be used together\n" if $o{k}+$o{m}>1;
6692 0 0       0 my @q=@ARGV; @q=('.') if !@q;
  0         0  
6693 0         0 my(%c,%b,$cnt,$bts,%mtime);
6694 0 0       0 my $r=$o{z} ? qr/(\.[^\.\/]{1,10}(\.(z|Z|gz|bz2|rz|xz))?)$/
6695             : qr/(\.[^\.\/]{1,10})$/;
6696 0 0       0 my $rexcl=exists$o{e}?qr/$o{e}/:0;
6697             File::Find::find({wanted =>
6698             sub {
6699 0 0   0   0 return if !-f$_;
6700 0 0 0     0 return if $rexcl and $File::Find::name=~$rexcl;
6701 0         0 my($sz,$mtime)=(stat($_))[7,9];
6702 0 0       0 my $ext=m/$r/?$1:"";
6703 0 0       0 $ext=lc($ext) if $o{i};
6704 0         0 $cnt++; $c{$ext}++;
  0         0  
6705 0         0 $bts+=$sz; $b{$ext}+=$sz;
  0         0  
6706 0 0 0     0 $mtime{$ext}.=",$mtime" if $o{M} or $o{P};
6707 0         0 1;
6708 0         0 } },@q);
6709 0     0   0 my($f,$s)=$o{k}?("%14.2f kb",sub{$_[0]/1024})
6710 0     0   0 :$o{K}?("%14.2f Kb",sub{$_[0]/1000})
6711 0     0   0 :$o{m}?("%14.2f mb",sub{$_[0]/1024**2})
6712 0     0   0 :$o{h}?("%14s", sub{bytes_readable($_[0])})
6713 0 0   0   0 : ("%14d b", sub{$_[0]});
  0 0       0  
    0          
    0          
6714             my @e=$o{a}?(sort(keys%c))
6715 0 0       0 :$o{c}?(sort{$c{$a}<=>$c{$b} or $a cmp $b}keys%c)
6716 0 0       0 : (sort{$b{$a}<=>$b{$b} or $a cmp $b}keys%c);
  0 0       0  
    0          
6717 0 0       0 my @p=$o{P}?(10,50,90):(50);
6718             my $perc=sub{
6719 0 0 0 0   0 $o{M} or $o{P} or return"";
6720 0         0 my @m=@_>0 ? do {grep$_, split",", $mtime{$_[0]}}
6721 0 0       0 : do {grep$_, map {split","} values %mtime};
  0         0  
  0         0  
6722 0         0 my @r=percentile(\@p,@m);
6723 0 0       0 @r=(min(@m),@r,max(@m)) if $o{M};
6724 0         0 @r=map int($_), @r;
6725 0 0       0 my $fmt='YYYY/MM/DD'; $fmt.="-MM:MI:SS" if $o{t};
  0         0  
6726 0         0 @r=map tms($_,$fmt), @r;
6727 0         0 " ".join(" ",@r);
6728 0         0 };
6729 0         0 printf("%-11s %8d $f %7.2f%%%s\n",$_,$c{$_},&$s($b{$_}),100*$b{$_}/$bts,&$perc($_)) for @e;
6730 0         0 printf("%-11s %8d $f %7.2f%%%s\n","Sum",$cnt,&$s($bts),100,&$perc());
6731             }
6732             sub cmd_xcat {
6733 0     0 0 0 for my $fn (@_){
6734 0         0 my $os=openstr($fn);
6735 0 0 0     0 open my $FH, $os or warn "xcat: cannot open $os ($!)\n" and next;
6736 0         0 print while <$FH>;
6737 0         0 close($FH);
6738             }
6739             }
6740             sub cmd_freq {
6741 0     0 0 0 my(@f,$i);
6742 0         0 map $f[$_]++, unpack("C*",$_) while <>;
6743 0         0 my $s=" " x 12;map{print"$_$s$_$s$_\n"}("BYTE CHAR COUNT","---- ----- -------");
  0         0  
  0         0  
6744 0         0 my %m=(145,"DOS-æ",155,"DOS-ø",134,"DOS-å",146,"DOS-Æ",157,"DOS-Ø",143,"DOS-Å",map{($_," ")}0..31);
  0         0  
6745 0 0 0     0 printf("%4d %5s%8d".(++$i%3?$s:"\n"),$_,$m{$_}||chr,$f[$_]) for grep$f[$_],0..255;print "\n";
  0         0  
6746 0         0 my @no=grep!$f[$_],0..255; print "No bytes for these ".@no.": ".join(" ",@no)."\n";
  0         0  
6747             }
6748              
6749             sub cmd_deldup {
6750             # ~/test/deldup.pl #find and optionally delete duplicate files effiencently
6751             #http://www.commandlinefu.com/commands/view/3555/find-duplicate-files-based-on-size-first-then-md5-hash
6752 0     0 0 0 die "todo: deldup not ready yet"
6753             }
6754              
6755             #http://stackoverflow.com/questions/11900239/can-i-cache-the-output-of-a-command-on-linux-from-cli
6756             our $Ccmd_cache_dir='/tmp/acme-tools-ccmd-cache';
6757             our $Ccmd_cache_expire=15*60; #default 15 minutes
6758             sub cmd_ccmd {
6759 0     0 0 0 require Digest::MD5;
6760 0         0 my $cmd=join" ",@_;
6761 0         0 my $d="$Ccmd_cache_dir/".username();
6762 0         0 makedir($d);
6763 0         0 my $md5=Digest::MD5::md5_hex($cmd);
6764 0         0 my($fno,$fne)=map"$d/cmd.$md5.std$_","out","err";
6765 0     0   0 my $too_old=sub{time()-(stat(shift))[9] >= $Ccmd_cache_expire};
  0         0  
6766 0         0 unlink grep &$too_old($_), <$d/*.std???>;
6767 0 0 0     0 sys("($cmd) > $fno 2> $fne") if !-e$fno or &$too_old($fno);
6768 0         0 print STDOUT "".readfile($fno);
6769 0         0 print STDERR "".readfile($fne);
6770             }
6771              
6772 0     0 0 0 sub cmd_trunc { die "todo: trunc not ready yet"} #truncate a file, size 0, keep all other attr
6773              
6774             sub cmd_wipe {
6775 0     0 0 0 require Getopt::Std; my %o; Getopt::Std::getopts("n:k" => \%o);
  0         0  
  0         0  
6776 0         0 wipe($_,$o{n},$o{k}) for @_;
6777             }
6778              
6779             =head1 DATABASE STUFF - NOT IMPLEMENTED YET
6780              
6781             Uses L. Comming soon...
6782              
6783             $Dbh
6784             dlogin
6785             dlogout
6786             drow
6787             drows
6788             drowc
6789             drowsc
6790             dcols
6791             dpk
6792             dsel
6793             ddo
6794             dins
6795             dupd
6796             ddel
6797             dcommit
6798             drollback
6799              
6800             =cut
6801              
6802             #my$dummy=<<'SOON';
6803             sub dtype {
6804 0     0 0 0 my $connstr=shift;
6805 0 0       0 return 'SQLite' if $connstr=~/(\.sqlite|sqlite:.*\.db)$/i;
6806 0 0       0 return 'Oracle' if $connstr=~/\@/;
6807 0         0 return 'Pg' if 1==2;
6808 0         0 die;
6809             }
6810              
6811             our($Dbh,@Dbh,%Sth);
6812             our %Dbattr=(RaiseError => 1, AutoCommit => 0); #defaults
6813             sub dlogin {
6814 0     0 0 0 my $connstr=shift();
6815 0         0 my %attr=(%Dbattr,@_);
6816 0         0 my $type=dtype($connstr);
6817 0         0 my($dsn,$u,$p)=('','','');
6818 0 0       0 if($type eq 'SQLite'){
    0          
    0          
6819 0         0 $dsn=$connstr;
6820             }
6821             elsif($type eq 'Oracle'){
6822 0         0 ($u,$p,$dsn)=($connstr=~m,(.+?)(/.+?)?\@(.+),);
6823             }
6824             elsif($type eq 'Pg'){
6825 0         0 croak "todo";
6826             }
6827             else{
6828 0         0 croak "dblogin: unknown database type for connection string $connstr\n";
6829             }
6830 0         0 $dsn="dbi:$type:$dsn";
6831 0 0       0 push @Dbh, $Dbh if $Dbh; #local is better?
6832 0         0 require DBI;
6833 0         0 $Dbh=DBI->connect($dsn,$u,$p,\%attr); #connect_cached?
6834             }
6835             sub dlogout {
6836 0     0 0 0 $Dbh->disconnect;
6837 0 0       0 $Dbh=pop@Dbh if @Dbh;
6838             }
6839             sub drow {
6840 0     0 0 0 my($q,@b)=_dattrarg(@_);
6841             #my $sth=do{$Sth{$Dbh,$q} ||= $Dbh->prepare_cached($q)};
6842 0         0 my $sth=$Dbh->prepare_cached($q);
6843 0         0 $sth->execute(@b);
6844 0         0 my @r=$sth->fetchrow_array;
6845 0 0       0 $sth->finish if $$Dbh{Driver}{Name} eq 'SQLite';
6846             #$dbh->selectrow_array($statement);
6847 0 0       0 return @r==1?$r[0]:@r;
6848             }
6849       0 0   sub drows {
6850             }
6851       0 0   sub drowc {
6852             }
6853       0 0   sub drowsc {
6854             }
6855       0 0   sub dcols {
6856             }
6857       0 0   sub dpk {
6858             }
6859       0 0   sub dsel {
6860             }
6861             sub ddo {
6862 0     0 0 0 my @arg=_dattrarg(@_);
6863             #warn serialize(\@arg,'arg','',1);
6864 0         0 $Dbh->do(@arg); #hm cache?
6865             }
6866       0 0   sub dins {
6867             }
6868       0 0   sub dupd {
6869             }
6870       0 0   sub ddel {
6871             }
6872 0     0 0 0 sub dcommit { $Dbh->commit }
6873 0     0 0 0 sub drollback { $Dbh->rollback }
6874              
6875             sub _dattrarg {
6876 0     0   0 my @arg=@_;
6877 0 0       0 splice @arg,1,0, ref($arg[-1]) eq 'HASH' ? pop(@arg) : {};
6878 0         0 @arg;
6879             }
6880              
6881             =head2 self_update
6882              
6883             Update Acme::Tools to newest version quick and dirty:
6884              
6885             function pmview(){ ls -ld `perl -M$1 -le'$m=shift;$mi=$m;$mi=~s,::,/,g;print $INC{"$mi.pm"};warn"Version ".${$m."::VERSION"}."\n"' $1`;}
6886              
6887             pmview Acme::Tools #view date and version before
6888             sudo perl -MAcme::Tools -e Acme::Tools::self_update #update to newest version
6889             pmview Acme::Tools #view date and version after
6890              
6891             Does C to where Acme/Tools.pm are and then wget -N https://raw.githubusercontent.com/kjetillll/Acme-Tools/master/Tools.pm
6892              
6893             =cut
6894              
6895             our $Wget;
6896             our $Self_update_url='https://raw.githubusercontent.com/kjetillll/Acme-Tools/master/Tools.pm'; #todo: change site
6897             sub self_update {
6898             #in($^O,'linux','cygwin') or die"ERROR: self_update works on linux and cygwin only";
6899 0   0 0 1 0 $Wget||=(grep -x$_,map"$_/wget",'/usr/bin','/bin','/usr/local/bin','.')[0]; #hm --no-check-certificate
6900 0 0       0 -x$Wget or die"ERROR: wget ($Wget) executable not found\n";
6901 0         0 my $d=dirname(__FILE__);
6902 0         0 sys("cd $d; ls -l Tools.pm; md5sum Tools.pm");
6903 0   0     0 sys("cd $d; $Wget -N ".($ARGV[0]||$Self_update_url));
6904 0         0 sys("cd $d; ls -l Tools.pm; md5sum Tools.pm");
6905             }
6906              
6907             1;
6908              
6909             package Acme::Tools::BloomFilter;
6910 28     28   768 use 5.008; use strict; use warnings; use Carp;
  28     28   101  
  28     28   141  
  28     28   50  
  28         738  
  28         132  
  28         46  
  28         969  
  28         143  
  28         46  
  28         14374  
6911 2     2   307 sub new { my($class,@p)=@_; my $self=Acme::Tools::bfinit(@p); bless $self, $class }
  2         9  
  2         11  
6912 2     2   108 sub add { &Acme::Tools::bfadd }
6913 0     0   0 sub addbf { &Acme::Tools::bfaddbf }
6914 2     2   88 sub check { &Acme::Tools::bfcheck }
6915 1     1   7 sub grep { &Acme::Tools::bfgrep }
6916 0     0   0 sub grepnot { &Acme::Tools::bfgrepnot }
6917 0     0   0 sub delete { &Acme::Tools::bfdelete }
6918 0     0   0 sub store { &Acme::Tools::bfstore }
6919 0     0   0 sub retrieve { &Acme::Tools::bfretrieve }
6920 1     1   5 sub clone { &Acme::Tools::bfclone }
6921 0     0   0 sub sum { &Acme::Tools::bfsum }
6922             1;
6923              
6924             # Ny versjon:
6925             # + c-s todo
6926             # + endre $VERSION
6927             # + endre Release history under HISTORY
6928             # + endre årstall under COPYRIGHT AND LICENSE
6929             # + oppd default valutakurser inkl datoen
6930             # + emacs Changes
6931             # + emacs README + aarstall
6932             # + emacs MANIFEST legg til ev nye t/*.t
6933             # + perl Makefile.PL;make test
6934             # + /usr/bin/perl Makefile.PL;make test
6935             # + perlbrew exec "perl ~/Acme-Tools/Makefile.PL ; time make test"
6936             # + perlbrew use perl-5.10.1; perl Makefile.PL; make test; perlbrew off
6937             # + test evt i cygwin og mingw-perl
6938             # + pod2html Tools.pm > Tools.html ; firefox Tools.html
6939             # + https://metacpan.org/pod/Acme::Tools
6940             # + http://cpants.cpanauthors.org/dist/Acme-Tools #kvalitee
6941             # + perl Makefile.PL ; make test && make dist
6942             # + cp -p *tar.gz /htdocs/
6943             # + ci -l -mversjon -d `cat MANIFEST`
6944             # + git add `cat MANIFEST`
6945             # + git status
6946             # + git commit -am versjon
6947             # + git push #eller:
6948             # + git push origin master
6949             # + http://pause.perl.org/
6950             # http://en.wikipedia.org/wiki/Birthday_problem#Approximations
6951              
6952             # memoize_expire() http://perldoc.perl.org/Memoize/Expire.html
6953             # memoize_file_expire()
6954             # memoize_limit_size() #lru
6955             # memoize_file_limit_size()
6956             # memoize_memcached http://search.cpan.org/~dtrischuk/Memoize-Memcached-0.03/lib/Memoize/Memcached.pm
6957             # hint on http://perl.jonallen.info/writing/articles/install-perl-modules-without-root
6958              
6959             # sub mycrc32 { #http://billauer.co.il/blog/2011/05/perl-crc32-crc-xs-module/ eller String::CRC32::crc32 som er 100 x raskere enn Digest::CRC::crc32
6960             # my ($input, $init_value, $polynomial) = @_;
6961             # $init_value = 0 unless (defined $init_value);
6962             # $polynomial = 0xedb88320 unless (defined $polynomial);
6963             # my @lookup_table;
6964             # for (my $i=0; $i<256; $i++) {
6965             # my $x = $i;
6966             # for (my $j=0; $j<8; $j++) {
6967             # if ($x & 1) {
6968             # $x = ($x >> 1) ^ $polynomial;
6969             # } else {
6970             # $x = $x >> 1;
6971             # }
6972             # }
6973             # push @lookup_table, $x;
6974             # }
6975             # my $crc = $init_value ^ 0xffffffff;
6976             # foreach my $x (unpack ('C*', $input)) {
6977             # $crc = (($crc >> 8) & 0xffffff) ^ $lookup_table[ ($crc ^ $x) & 0xff ];
6978             # }
6979             # $crc = $crc ^ 0xffffffff;
6980             # return $crc;
6981             # }
6982             #
6983              
6984              
6985              
6986             =head1 HISTORY
6987              
6988             Release history
6989              
6990             0.172 Dec 2015 Subs: curb, openstr, pwgen, sleepms, sleepnm, srlz, tms, username,
6991             self_update, install_acme_command_tools
6992             Commands: conv, due, freq, wipe, xcat (see "Commands")
6993             0.16 Feb 2015 bigr, curb, cpad, isnum, parta, parth, read_conf, resolve_equation,
6994             roman2int, trim. Improved: conv (numbers, currency), range ("derivatives")
6995             0.15 Nov 2014 Improved doc
6996             0.14 Nov 2014 New subs, improved tests and doc
6997             0.13 Oct 2010 Non-linux test issue, resolve. improved: bloom filter, tests, doc
6998             0.12 Oct 2010 Improved tests, doc, bloom filter, random_gauss, bytes_readable
6999             0.11 Dec 2008 Improved doc
7000             0.10 Dec 2008
7001              
7002             =head1 SEE ALSO
7003              
7004             L
7005              
7006             =head1 AUTHOR
7007              
7008             Kjetil Skotheim, Ekjetil.skotheim@gmail.comE
7009              
7010             =head1 COPYRIGHT
7011              
7012             1995-2015, Kjetil Skotheim
7013              
7014             =head1 LICENSE
7015              
7016             This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
7017              
7018             =cut