#! perl -slw use strict; use List::Util qw[ sum ]; use List::MoreUtils qw[ lastidx ]; use Data::Dump qw[ pp ]; $Data::Dump::WIDTH = 1000; $|++; our $MACHMAX //= 85000; ## Read data and consolidate flows by chemical; loose original machine info. my %chems; while( ) { my( $chem, $mach, $flow ) = split ' '; next unless $flow; push @{ $chems{ sprintf "%1s%03d", $chem =~ m[(.)(\d+)] } }, $flow; } ## Now total the flows for each chemical and divide those totals greater than MACHMAX across multiple machines. my( $iMach, %machs ) = 0; for my $chem ( keys %chems ) { my $nozzles = $chems{ $chem }; @{ $nozzles } = sort{ $b <=> $a } @{ $nozzles }; my $total = sum @{ $nozzles }; ## create a machine with one nozzle for all flows of the current chemical my $mach = sprintf "E%03d", ++$iMach; $machs{ $mach } = { TOTAL => $total, nozzles =>[ $chem, delete $chems{ $chem } ] }; ## If the total requirement for this chemical is too big for one machine ## break it up into 2 or more machines. while( $machs{ $mach }{ TOTAL } > $MACHMAX ) { ## create a new machine and start it with the largest flow from this chemical my $newMach = sprintf "E%03d", ++$iMach; my $first = shift @{ $machs{ $mach }{ nozzles }[1] }; $machs{ $newMach } = { TOTAL => $first, nozzles => [ $chem , [ $first ] ] }; $machs{ $mach }{ TOTAL } -= $machs{ $newMach }{ TOTAL }; ## Then populate newmach from mach whilst mach contains a nozzle that will fit while( my $idx = 1+ lastidx{ ( $machs{ $newMach }{ TOTAL } + $_ ) < $MACHMAX } @{ $machs{ $mach }{ nozzles }[1] } ) { my $swapVal = splice @{ $machs{ $mach }{ nozzles }[1] }, $idx-1, 1; push @{ $machs{ $newMach }{ nozzles }[1] }, $swapVal; $machs{ $newMach }{ TOTAL } += $swapVal; $machs{ $mach }{ TOTAL } -= $swapVal; } } } #pp \%machs; #for my $key ( sort{ $machs{ $a }{ nozzles }[0] cmp $machs{ $b }{ nozzles }[0] } keys %machs ) { # printf "%s : total=%8.2f\n", $key, $machs{ $key }{ TOTAL }; # for( my $i=0; $i < @{ $machs{ $key }{ nozzles } }; $i += 2 ) { # printf "\t%6s : [ %s ]\n", $machs{ $key }{ nozzles }[ $i ], join ', ', @{ $machs{ $key }{ nozzles }[ 1 ] }; # } #} print "After flow consolidation:"; printf "Total machines:%d total nozzles:%d\n", scalar keys %machs, sum( map{ @{ $machs{ $_ }{ nozzles } } / 2 } keys %machs ); my $idle = ( $MACHMAX * keys %machs ) - sum( map{ $machs{ $_ }{ TOTAL } } keys %machs ); printf "Total idle capacity:%d (~%d machines)\n\n", $idle, 1+int( $idle / $MACHMAX ); ## Now reduce the number of machines by combining chemicals onto 1 machine without splitting them across machines. my @keysByTotal = sort{ $machs{ $b }{ TOTAL } <=> $machs{ $a }{ TOTAL } } keys %machs; for my $key ( @keysByTotal ) { while( my $idx = 1+ lastidx{ ( ($machs{ $key }{ TOTAL }//0) + $machs{ $_ }{ TOTAL } ) < $MACHMAX } @keysByTotal ) { my $swapKey = splice @keysByTotal, --$idx, 1; push @{ $machs{ $key }{ nozzles } }, @{ $machs{ $swapKey }{ nozzles } }; $machs{ $key }{ TOTAL } += $machs{ $swapKey }{ TOTAL }; delete $machs{ $swapKey }; } } ## Renumber machines to fill gaps left by the above machine consolidation phase. $iMach = 0; for my $key ( sort keys %machs ) { $machs{ sprintf "E%03d", ++$iMach } = delete $machs{ $key }; } #pp \%machs; for my $key ( sort keys %machs ) { printf "%s : total=%8.2f\n", $key, $machs{ $key }{ TOTAL }; for( my $i=0; $i < @{ $machs{ $key }{ nozzles } }; $i += 2 ) { printf "\t%6s : [ %s ]\n", $machs{ $key }{ nozzles }[ $i ], join ', ', @{ $machs{ $key }{ nozzles }[ $i+1 ] }; } } print "\n\nAfter machine consolidation:"; printf "Total machines:%d total nozzles:%d\n", scalar keys %machs, sum( map{ @{ $machs{ $_ }{ nozzles } } / 2 } keys %machs ); $idle = ( $MACHMAX * keys %machs ) - sum( map{ $machs{ $_ }{ TOTAL } } keys %machs ); printf "Total idle capacity:%d (~%d machines)\n", $idle, 1+int( $idle / $MACHMAX ); __DATA__ C55 E1 539.85 C55 E1 9458.172 C56 E1 548.7 C56 E1 6869.724 C59 E1 2208.96 C59 E1 3185.8584 C59 E1 847.6884 C59 E1 6949.02 C60 E1 6731.8056 C61 E1 3811.5888 C61 E1 1546.272 C62 E1 13215.2448 C62 E1 543.39 C63 E1 10392.8736 C15 E10 3468.138 C15 E10 13323.6396 C19 E10 0 C19 E10 23934.8604 C19 E10 2891.2596 C20 E10 1331.748 C20 E10 0 C20 E10 17930.808 C20 E10 9302.8368 C20 E10 2884.392 C43 E10 15787.5504 C43 E10 1462.02 C43 E10 555.5676 C15 E11 1436.2488 C15 E11 0 C15 E11 791.19 C15 E11 0 C15 E11 703.4688 C15 E11 6234.5772 C15 E11 14837.91 C15 E11 0 C15 E11 1501.668 C15 E11 2386.0308 C16 E11 5810.91 C22 E11 14198.232 C22 E11 3760.6128 C22 E11 959.34 C22 E11 0 C36 E11 6818.5356 C36 E11 2777.13 C36 E11 883.23 C42 E11 0 C42 E11 1537.9884 C42 E11 0 C42 E11 18219.2472 C9 E11 8391.924 C9 E11 759.33 C9 E11 1305.4104 C9 E11 2035.0044 C9 E11 727.47 C16 E12 4290.48 C16 E12 34161.9912 C16 E12 5819.76 C16 E12 9457.11 C16 E12 4261.8768 C27 E12 26777.6928 C27 E12 4062.15 C16 E13 7274.7 C16 E13 13821.93 C23 E13 7869.42 C23 E13 14864.46 C23 E13 13990.08 C27 E13 25997.76 C27 E13 21090.6828 C16 E14 22882.56 C16 E14 36411.8736 C16 E14 3546.7968 C23 E14 23573.2848 C15 E15 0 C20 E15 0 C22 E15 9324.7848 C23 E15 4371.9 C23 E15 24447.6648 C27 E15 4230.3 C27 E15 29056.32 C27 E15 21892.3512 C9 E15 698.3712 C9 E15 0 C9 E15 1522.9788 C15 E16 5720.64 C27 E16 21151.5 C27 E16 15682.2 C27 E16 19602.75 C27 E16 22482.54 C9 E16 0 C9 E16 10448.3808 C9 E16 10068.1848 C15 E17 24504.1632 C15 E17 1430.16 C16 E17 6375.3984 C19 E17 4471.02 C20 E17 15611.4 C21 E17 15559.1496 C27 E17 3101.04 C43 E17 10575.5376 C15 E18 12250.6656 C15 E18 4380.3252 C15 E18 1716.192 C15 E18 5255.838 C27 E18 9409.32 C36 E18 14996.502 C36 E18 883.23 C41 E18 10822.2048 C42 E18 0 C43 E18 23977.128 C9 E18 6775.7016 C9 E18 727.47 C9 E18 3735.9036 C9 E18 2851.6824 C9 E18 3822.9876 C9 E18 58.1976 C11 E19 571.71 C11 E19 536.31 C11 E19 2145.24 C11 E19 1603.62 C12 E19 4463.232 C12 E19 5671.3632 C12 E19 14273.28 C12 E19 6281.73 C13 E19 6690.6 C13 E19 7315.1268 C13 E19 3874.53 C70 E19 19788.6 C71 E19 4134.72 C71 E19 4134.72 C56 E2 0 C56 E2 383.5944 C59 E2 62.8704 C59 E2 0 C59 E2 0 C63 E2 880.752 C65 E2 9060.1344 C65 E2 1755.84 C65 E2 18787.488 C66 E2 6855.6348 C66 E2 5865.426 C68 E2 5085.0684 C68 E2 2884.1088 C11 E20 5302.6368 C11 E20 13817.8944 C11 E20 1603.62 C11 E20 7440.7968 C11 E20 1143.42 C12 E20 11068.3056 C12 E20 5819.3352 C12 E20 3735.762 C12 E20 7258.9824 C12 E20 2832 C38 E20 9604.728 C6 E20 0 C6 E20 0 C6 E20 0 C6 E20 0 C6 E20 0 C6 E20 0 C6 E20 0 C6 E20 0 C6 E20 0 C6 E20 0 C6 E20 0 C70 E20 576.0288 C70 E20 456.0228 C70 E20 11496.5748 C13 E21 2442.6 C13 E21 13190.04 C14 E21 3978.96 C14 E21 39789.6 C14 E21 2984.22 C14 E21 12931.62 C14 E21 4476.33 C1 E22 1026.6 C1 E22 499.5648 C11 E22 1566.0252 C11 E22 1074.8148 C11 E22 5901.3216 C11 E22 2469.0792 C11 E22 6435.72 C11 E22 1026.3168 C11 E22 12648.2076 C11 E22 4276.32 C11 E22 1692.2616 C11 E22 3207.24 C12 E22 11145.5484 C12 E22 462.1824 C12 E22 566.4 C12 E22 343.026 C12 E22 350.0352 C12 E22 2812.8132 C12 E22 6071.808 C12 E22 1022.9184 C12 E22 552.24 C12 E22 1669.3932 C12 E22 1029.7152 C6 E22 0 C71 E22 4134.72 C71 E22 1550.52 C71 E22 9819.96 C13 E23 7042.3344 C13 E23 15214.92 C33 E23 4028.3784 C33 E23 16761.7584 C71 E23 10316.1264 C71 E23 4134.72 C71 E23 4651.56 C71 E23 17055.72 C1 E24 1026.6 C1 E24 513.3 C11 E24 2123.7876 C11 E24 13446.6192 C11 E24 7376.652 C11 E24 12807.0828 C11 E24 2523.0288 C11 E24 571.71 C11 E24 534.54 C11 E24 1072.62 C11 E24 536.31 C11 E24 534.54 C11 E24 4276.32 C11 E24 536.31 C11 E24 6392.3904 C12 E24 1087.488 C12 E24 11228.88 C12 E24 2265.6 C12 E24 3452.3496 C12 E24 2195.3664 C12 E24 571.71 C12 E24 536.31 C12 E24 575.25 C12 E24 0 C12 E24 5841.2124 C12 E24 2876.25 C12 E24 3217.86 C12 E24 525.9732 C38 E24 1143.42 C70 E24 1633.71 C70 E24 0 C11 E25 6991.7832 C11 E25 9052.9128 C11 E25 4233.5568 C11 E25 2681.55 C11 E25 2629.9368 C11 E25 21495.3048 C12 E25 7965.8496 C12 E25 490.1484 C12 E25 12292.2252 C13 E25 5977.29 C24 E26 4854.3312 C25 E26 18737.5032 C26 E26 2173.7016 C26 E26 2755.3944 C28 E26 483.21 C28 E26 1523.97 C28 E26 8562.4812 C28 E26 4862.8272 C28 E26 2418.7404 C29 E26 6377.0976 C30 E26 2109.84 C30 E26 12659.04 C37 E26 6626.88 C8 E26 4450.2048 C1 E27 0 C24 E27 994.74 C25 E27 3165.0432 C25 E27 0 C25 E27 1790.532 C25 E27 0 C25 E27 461.97 C25 E27 3765.852 C25 E27 3714.876 C25 E27 2288.964 C25 E27 4652.976 C25 E27 4106.1168 C25 E27 879.336 C25 E27 6822.8544 C25 E27 923.94 C26 E27 3729.39 C26 E27 2131.08 C26 E27 2663.85 C26 E27 5860.47 C28 E27 507.99 C28 E27 1015.98 C28 E27 457.0848 C28 E27 1894.1832 C28 E27 2158.8336 C28 E27 1015.98 C28 E27 1199.8476 C30 E27 3164.76 C30 E27 527.46 C31 E27 0 C32 E27 7803.7884 C35 E27 0 C37 E27 3186 C40 E27 0 C40 E27 0 C7 E27 0 C8 E27 1133.154 C8 E27 803.5092 C25 E28 490.29 C25 E28 6373.77 C25 E28 4902.9 C25 E28 490.29 C25 E28 14218.41 C26 E28 10570.1568 C26 E28 5860.47 C26 E28 3729.39 C28 E28 6603.87 C28 E28 4571.91 C28 E28 3047.94 C28 E28 1599.7968 C25 E29 2451.45 C25 E29 3432.03 C25 E29 75.048 C25 E29 573.48 C25 E29 3392.8776 C25 E29 6595.02 C25 E29 1731.06 C25 E29 1731.06 C25 E29 9081.516 C25 E29 7354.35 C25 E29 73.9152 C26 E29 7970.2392 C26 E29 6393.24 C26 E29 11102.9268 C28 E29 2519.6304 C28 E29 4571.91 C28 E29 1523.97 C39 E29 571.71 C39 E29 571.71 C8 E29 7624.8768 C8 E29 82.4112 C1 E3 0 C51 E3 0 C52 E3 0 C56 E3 0 C56 E3 2186.8704 C56 E3 2578.6068 C56 E3 5901.0384 C56 E3 0 C58 E3 5970.8472 C58 E3 0 C59 E3 0 C59 E3 0 C59 E3 8889.8604 C59 E3 506.22 C59 E3 0 C61 E3 0 C63 E3 0 C63 E3 0 C63 E3 0 C1 E30 0 C1 E30 0 C1 E30 0 C2 E30 7975.9032 C2 E30 4600.584 C2 E30 0 C2 E30 0 C2 E30 909.78 C2 E30 0 C2 E30 12540.2376 C2 E30 279.66 C2 E30 0 C2 E30 472.1652 C2 E30 9097.8 C2 E30 0 C2 E30 0 C2 E30 0 C2 E30 1751.1672 C2 E30 0 C1 E31 1053.15 C1 E31 22790.166 C1 E31 2064.174 C17 E31 2465.61 C17 E31 1972.488 C17 E31 7298.2056 C17 E31 14695.0356 C1 E32 0 C2 E32 3788.4372 C2 E32 1348.74 C2 E32 6743.7 C2 E32 1078.992 C2 E32 1297.41 C2 E32 3992.2704 C2 E32 27401.2992 C1 E33 0 C1 E33 0 C1 E33 0 C1 E33 0 C18 E33 23211.426 C18 E33 1053.15 C18 E33 3075.198 C1 E34 0 C2 E34 6749.4348 C3 E35 1522.9788 C3 E35 4610.0004 C3 E35 2331.09 C3 E35 1505.4912 C3 E35 31858.23 C34 E35 0 C44 E4 6781.0824 C57 E4 923.94 C58 E4 10519.11 C58 E4 2003.64 C59 E4 1104.48 C60 E4 254.0304 C62 E4 412.9764 C64 E4 0 C65 E4 5267.52 C65 E4 3072.72 C67 E4 467.28 C67 E4 1869.12 C68 E4 1904.52 C68 E4 474.36 C68 E4 2846.16 C69 E4 476.13 C69 E4 1383.1488 C69 E4 476.13 C69 E4 467.28 C55 E5 1619.55 C55 E5 1619.55 C56 E5 4301.808 C59 E5 6096.7296 C59 E5 1104.48 C59 E5 0 C59 E5 11652.972 C60 E5 8658.2028 C60 E5 529.23 C61 E5 5961.1476 C61 E5 6980.3136 C62 E5 9672.342 C62 E5 1086.78 C63 E5 506.4324 C64 E5 42.0552 C47 E6 4141.8 C55 E6 17815.05 C59 E6 4212.1752 C59 E6 16037.0496 C61 E6 1457.9136 C63 E6 1585.3536 C64 E6 19976.22 C65 E6 877.92 C65 E6 1773.3984 C68 E6 3320.52 C68 E6 952.26 C68 E6 8094.21 C47 E7 3552.744 C47 E7 5614.44 C47 E7 11044.8 C47 E7 2282.592 C47 E7 21905.52 C10 E8 10531.146 C4 E8 3023.16 C45 E8 13927.4928 C45 E8 861.4944 C46 E8 9586.8864 C48 E8 5920.4376 C48 E8 6549.8496 C49 E8 0 C5 E8 9588.444 C5 E8 0 C5 E8 826.59 C54 E8 5200.8264 C10 E9 4449.78 C4 E9 1511.58 C45 E9 861.4944 C45 E9 13855.7016 C45 E9 717.912 C46 E9 19876.1088 C46 E9 2633.76 C48 E9 7151.3664 C48 E9 7948.4328 C5 E9 0 C50 E9 19529.6136 C50 E9 1996.56 C50 E9 5350.9932 C50 E9 3023.16 C53 E9 0 C54 E9 3073.2156