(see also: Reload a script with a new value for input when submit is clicked on an html form)
A couple of days ago, I decided to write a script which would change the appearance of the font of some displayed text in HTML. To do that, I needed to nest some loops. So, I wrote the loops and everything was wonderful. I needed some help to make the script functional. After I got the help and a functioning script, I decided to add more loops to it. After I did that but before I ran it in my browser again and on a whim, I decided to do some math. The math made me stop and wonder what I had just done.
In the script, I am looping two hashes. Each hash value is an array. Well, multiplying the amounts of values in each array showed me just how many iterations there were going to be. Then I multiplied that by the approximate amount of text that would be generated, and I got a really really really really really big number. That big number made me sit back and realize I need to rethink the whole thing. I still need the loops, but do I really want to display all options when the script it first loaded? The answer of course is no.
The script below generates approximately 145 Mb of text when nothing is selected. Even if one item (with the least options) is selected, it would still generate approximately 50 Mb of text. That is a bit much, don't you think? :)
What was learned? Be careful when nesting loops since it grows exponentially.
#!/usr/bin/perl use strict; use warnings; use CGI; use HTML::Entities qw(encode_entities); use Tie::IxHash; print "content-type: text/html \n\n"; my @options = qw(text color background_color); tie my %font, qw(Tie::IxHash); tie my %text, qw(Tie::IxHash); %font = ( style => [qw(normal italic oblique)], variant => [qw(normal small-caps)], weight => [qw(normal bold 100 200 300 400 500 600 700 800 900)] +, size => [qw(xx-small x-small small medium large x-large xx-la +rge)], family => [qw(serif sans-serif cursive fantasy monospace)], ); %text = ( align => [qw(left right center justify)], decoration => [qw(none underline overline line-through blink)], transform => [qw(none capitalize uppercase lowercase)], ); my $cgi = CGI->new(); my $text = encode_entities($cgi->param('text')) || "The q +uick brown fox jumps over the lazy dog."; my $color = encode_entities($cgi->param('color')) || "#000 +"; my $background_color = encode_entities($cgi->param('background_color' +)) || "transparent"; my $select_style = $cgi->param('select_style'); my $select_variant = $cgi->param('select_variant'); my $select_weight = $cgi->param('select_weight'); my $select_size = $cgi->param('select_size'); my $select_family = $cgi->param('select_family'); my $select_align = $cgi->param('select_align'); my $select_decoration = $cgi->param('select_decoration'); my $select_transform = $cgi->param('select_transform'); sub select_group { my ($value, $hash) = @_; my $display_value = ucfirst $value; print qq{<div>\n<span>$display_value: </span>\n}; for my $select (keys %$hash) { my $options = $$hash{$select}; print qq{<select name="select_$select:">\n}; my $label = $select; print qq{<option value="">$label</option>\n}; for my $option (@$options) { print qq{<option value="$option">$option</option>\n}; } print qq{</select>\n}; } print qq{</div>\n}; } print <<"sec1"; <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/T +R/html4/strict.dtd"> <html><head><title>Font, text, and color tests</title> <style type="text/css"> h1 {font-size:14pt;} </style> </head> <body> <h1Font, text, and color tests</h1> <form action="/fantasy/files/perl/font.pl" method="get"> sec1 for my $option (@options) { my $display_option = ucfirst $option; $display_option =~ tr/_/ /; print qq{<div>\n<label for="$option">$display_option: </label>\n<inp +ut type="text" id="$option" name="$option">\n</div>}; } select_group('font', \%font); select_group('text', \%text); print <<"sec2"; <div> <input type="submit" value="submit"> <a href="font.pl">Start over</a> </div> </form> sec2 #Begin the OH MY GOD THIS IS HUGE! loop for my $style ($select_style ? $select_style : @{$font{'style'}}) { for my $variant ($select_variant ? $select_variant: @{$font{'variant +'}}) { for my $weight ($select_weight ? $select_weight : @{$font{'weight' +}}) { for my $size ($select_size ? $select_size : @{$font{'size'}}) { for my $family ($select_family ? $select_family : @{$font{'fam +ily'}}) { for my $align ($select_align ? $select_align : @{$text{'alig +n'}}) { for my $decoration ($select_decoration ? $select_decoratio +n : @{$text{'decoration'}}) { for my $transform ($select_transform ? $select_transform + : @{$text{'transform'}}) { print qq{ #Outdented for visibility and ease of editing <dl>\n <dt>font-<dt>\n <dd>style: $style; variant: $variant; weight: $weight; size: $size; fa +mily: $family;</dd>\n <dt>text-</dt>\n <dd>align: $align; decoration: $decoration; transform: $transform;<dd> +\n <dt>color<dt>\n <dd>$color</dd>\n <dt>background-color</dt>\n <dd>$background_color</dd>\n <dl>\n }; print qq{ #Outdented for visibility and ease of editing <p style=" font:$style $variant $weight $size $family; text-align:$align;text-decoration:$decoration;text-transform:$transfor +m; color:$color;background-color:$background_color; ">$text</p>\n }; } } } } } } } } #End the OH MY GOD THIS IS HUGE! loop print "</body></html>";
PS. If you have any thoughts that might help me with the rethink, I will take them.
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |