| // chameneos |
| |
| extern mod std; |
| use std::map; |
| use std::map::HashMap; |
| use std::sort; |
| |
| fn print_complements() { |
| let all = ~[Blue, Red, Yellow]; |
| for vec::each(all) |aa| { |
| for vec::each(all) |bb| { |
| io::println(show_color(*aa) + ~" + " + show_color(*bb) + |
| ~" -> " + show_color(transform(*aa, *bb))); |
| } |
| } |
| } |
| |
| enum color { Red, Yellow, Blue } |
| |
| type creature_info = { name: uint, color: color }; |
| |
| fn show_color(cc: color) -> ~str { |
| match (cc) { |
| Red => {~"red"} |
| Yellow => {~"yellow"} |
| Blue => {~"blue"} |
| } |
| } |
| |
| fn show_color_list(set: ~[color]) -> ~str { |
| let mut out = ~""; |
| for vec::eachi(set) |_ii, col| { |
| out += ~" "; |
| out += show_color(*col); |
| } |
| return out; |
| } |
| |
| fn show_digit(nn: uint) -> ~str { |
| match (nn) { |
| 0 => {~"zero"} |
| 1 => {~"one"} |
| 2 => {~"two"} |
| 3 => {~"three"} |
| 4 => {~"four"} |
| 5 => {~"five"} |
| 6 => {~"six"} |
| 7 => {~"seven"} |
| 8 => {~"eight"} |
| 9 => {~"nine"} |
| _ => {fail ~"expected digits from 0 to 9..."} |
| } |
| } |
| |
| fn show_number(nn: uint) -> ~str { |
| let mut out = ~""; |
| let mut num = nn; |
| let mut dig; |
| |
| if num == 0 { out = show_digit(0) }; |
| |
| while num != 0 { |
| dig = num % 10; |
| num = num / 10; |
| out = show_digit(dig) + ~" " + out; |
| } |
| |
| return out; |
| } |
| |
| fn transform(aa: color, bb: color) -> color { |
| match (aa, bb) { |
| (Red, Red ) => { Red } |
| (Red, Yellow) => { Blue } |
| (Red, Blue ) => { Yellow } |
| (Yellow, Red ) => { Blue } |
| (Yellow, Yellow) => { Yellow } |
| (Yellow, Blue ) => { Red } |
| (Blue, Red ) => { Yellow } |
| (Blue, Yellow) => { Red } |
| (Blue, Blue ) => { Blue } |
| } |
| } |
| |
| fn creature( |
| name: uint, |
| color: color, |
| from_rendezvous: comm::Port<Option<creature_info>>, |
| to_rendezvous: comm::Chan<creature_info>, |
| to_rendezvous_log: comm::Chan<~str> |
| ) { |
| let mut color = color; |
| let mut creatures_met = 0; |
| let mut evil_clones_met = 0; |
| |
| loop { |
| // ask for a pairing |
| comm::send(to_rendezvous, {name: name, color: color}); |
| let resp = comm::recv(from_rendezvous); |
| |
| // log and change, or print and quit |
| match resp { |
| option::Some(other_creature) => { |
| color = transform(color, other_creature.color); |
| |
| // track some statistics |
| creatures_met += 1; |
| if other_creature.name == name { |
| evil_clones_met += 1; |
| } |
| } |
| option::None => { |
| // log creatures met and evil clones of self |
| let report = fmt!("%u", creatures_met) + ~" " + |
| show_number(evil_clones_met); |
| comm::send(to_rendezvous_log, report); |
| break; |
| } |
| } |
| } |
| } |
| |
| fn rendezvous(nn: uint, set: ~[color]) { |
| // these ports will allow us to hear from the creatures |
| let from_creatures: comm::Port<creature_info> = comm::Port(); |
| let from_creatures_log: comm::Port<~str> = comm::Port(); |
| |
| // these channels will be passed to the creatures so they can talk to us |
| let to_rendezvous = comm::Chan(&from_creatures); |
| let to_rendezvous_log = comm::Chan(&from_creatures_log); |
| |
| // these channels will allow us to talk to each creature by 'name'/index |
| let to_creature: ~[comm::Chan<Option<creature_info>>] = |
| vec::mapi(set, |ii, col| { |
| // create each creature as a listener with a port, and |
| // give us a channel to talk to each |
| let ii = ii; |
| let col = *col; |
| do task::spawn_listener |from_rendezvous, move ii, move col| { |
| creature(ii, col, from_rendezvous, to_rendezvous, |
| to_rendezvous_log); |
| } |
| }); |
| |
| let mut creatures_met = 0; |
| |
| // set up meetings... |
| for nn.times { |
| let fst_creature: creature_info = comm::recv(from_creatures); |
| let snd_creature: creature_info = comm::recv(from_creatures); |
| |
| creatures_met += 2; |
| |
| comm::send(to_creature[fst_creature.name], Some(snd_creature)); |
| comm::send(to_creature[snd_creature.name], Some(fst_creature)); |
| } |
| |
| // tell each creature to stop |
| for vec::eachi(to_creature) |_ii, to_one| { |
| comm::send(*to_one, None); |
| } |
| |
| // save each creature's meeting stats |
| let mut report = ~[]; |
| for vec::each(to_creature) |_to_one| { |
| report.push(comm::recv(from_creatures_log)); |
| } |
| |
| // print each color in the set |
| io::println(show_color_list(set)); |
| |
| // print each creature's stats |
| for vec::each(report) |rep| { |
| io::println(*rep); |
| } |
| |
| // print the total number of creatures met |
| io::println(show_number(creatures_met)); |
| } |
| |
| fn main() { |
| let args = os::args(); |
| let args = if os::getenv(~"RUST_BENCH").is_some() { |
| ~[~"", ~"200000"] |
| } else if args.len() <= 1u { |
| ~[~"", ~"600"] |
| } else { |
| args |
| }; |
| |
| let nn = uint::from_str(args[1]).get(); |
| |
| print_complements(); |
| io::println(~""); |
| |
| rendezvous(nn, ~[Blue, Red, Yellow]); |
| io::println(~""); |
| |
| rendezvous(nn, |
| ~[Blue, Red, Yellow, Red, Yellow, Blue, Red, Yellow, Red, Blue]); |
| } |
| |