]> git.lizzy.rs Git - rust.git/blob - src/test/bench/shootout-chameneos-redux.rs
test: Make manual changes to deal with the fallout from removal of
[rust.git] / src / test / bench / shootout-chameneos-redux.rs
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 // chameneos
12
13 use std::option;
14 use std::os;
15 use std::task;
16 use std::vec_ng::Vec;
17
18 fn print_complements() {
19     let all = [Blue, Red, Yellow];
20     for aa in all.iter() {
21         for bb in all.iter() {
22             println!("{} + {} -> {}", show_color(*aa), show_color(*bb),
23                 show_color(transform(*aa, *bb)));
24         }
25     }
26 }
27
28 enum color { Red, Yellow, Blue }
29
30 struct CreatureInfo {
31     name: uint,
32     color: color
33 }
34
35 fn show_color(cc: color) -> ~str {
36     match cc {
37         Red    => {~"red"}
38         Yellow => {~"yellow"}
39         Blue   => {~"blue"}
40     }
41 }
42
43 fn show_color_list(set: Vec<color>) -> ~str {
44     let mut out = ~"";
45     for col in set.iter() {
46         out.push_char(' ');
47         out.push_str(show_color(*col));
48     }
49     return out;
50 }
51
52 fn show_digit(nn: uint) -> ~str {
53     match nn {
54         0 => {~"zero"}
55         1 => {~"one"}
56         2 => {~"two"}
57         3 => {~"three"}
58         4 => {~"four"}
59         5 => {~"five"}
60         6 => {~"six"}
61         7 => {~"seven"}
62         8 => {~"eight"}
63         9 => {~"nine"}
64         _ => {fail!("expected digits from 0 to 9...")}
65     }
66 }
67
68 fn show_number(nn: uint) -> ~str {
69     let mut out = ~"";
70     let mut num = nn;
71     let mut dig;
72
73     if num == 0 { out = show_digit(0) };
74
75     while num != 0 {
76         dig = num % 10;
77         num = num / 10;
78         out = show_digit(dig) + " " + out;
79     }
80
81     return ~" " + out;
82 }
83
84 fn transform(aa: color, bb: color) -> color {
85     match (aa, bb) {
86         (Red,    Red   ) => { Red    }
87         (Red,    Yellow) => { Blue   }
88         (Red,    Blue  ) => { Yellow }
89         (Yellow, Red   ) => { Blue   }
90         (Yellow, Yellow) => { Yellow }
91         (Yellow, Blue  ) => { Red    }
92         (Blue,   Red   ) => { Yellow }
93         (Blue,   Yellow) => { Red    }
94         (Blue,   Blue  ) => { Blue   }
95     }
96 }
97
98 fn creature(
99     name: uint,
100     color: color,
101     from_rendezvous: Receiver<Option<CreatureInfo>>,
102     to_rendezvous: Sender<CreatureInfo>,
103     to_rendezvous_log: Sender<~str>
104 ) {
105     let mut color = color;
106     let mut creatures_met = 0;
107     let mut evil_clones_met = 0;
108
109     loop {
110         // ask for a pairing
111         to_rendezvous.send(CreatureInfo {name: name, color: color});
112         let resp = from_rendezvous.recv();
113
114         // log and change, or print and quit
115         match resp {
116             option::Some(other_creature) => {
117                 color = transform(color, other_creature.color);
118
119                 // track some statistics
120                 creatures_met += 1;
121                 if other_creature.name == name {
122                    evil_clones_met += 1;
123                 }
124             }
125             option::None => {
126                 // log creatures met and evil clones of self
127                 let report = format!("{} {}",
128                                      creatures_met, show_number(evil_clones_met));
129                 to_rendezvous_log.send(report);
130                 break;
131             }
132         }
133     }
134 }
135
136 fn rendezvous(nn: uint, set: Vec<color>) {
137
138     // these ports will allow us to hear from the creatures
139     let (to_rendezvous, from_creatures) = channel::<CreatureInfo>();
140     let (to_rendezvous_log, from_creatures_log) = channel::<~str>();
141
142     // these channels will be passed to the creatures so they can talk to us
143
144     // these channels will allow us to talk to each creature by 'name'/index
145     let mut to_creature: Vec<Sender<Option<CreatureInfo>>> =
146         set.iter().enumerate().map(|(ii, col)| {
147             // create each creature as a listener with a port, and
148             // give us a channel to talk to each
149             let ii = ii;
150             let col = *col;
151             let to_rendezvous = to_rendezvous.clone();
152             let to_rendezvous_log = to_rendezvous_log.clone();
153             let (to_creature, from_rendezvous) = channel();
154             task::spawn(proc() {
155                 creature(ii,
156                          col,
157                          from_rendezvous,
158                          to_rendezvous.clone(),
159                          to_rendezvous_log.clone());
160             });
161             to_creature
162         }).collect();
163
164     let mut creatures_met = 0;
165
166     // set up meetings...
167     for _ in range(0, nn) {
168         let mut fst_creature: CreatureInfo = from_creatures.recv();
169         let mut snd_creature: CreatureInfo = from_creatures.recv();
170
171         creatures_met += 2;
172
173         to_creature.get_mut(fst_creature.name).send(Some(snd_creature));
174         to_creature.get_mut(snd_creature.name).send(Some(fst_creature));
175     }
176
177     // tell each creature to stop
178     for to_one in to_creature.iter() {
179         to_one.send(None);
180     }
181
182     // save each creature's meeting stats
183     let mut report = Vec::new();
184     for _to_one in to_creature.iter() {
185         report.push(from_creatures_log.recv());
186     }
187
188     // print each color in the set
189     println!("{}", show_color_list(set));
190
191     // print each creature's stats
192     for rep in report.iter() {
193         println!("{}", *rep);
194     }
195
196     // print the total number of creatures met
197     println!("{}", show_number(creatures_met));
198 }
199
200 fn main() {
201     let args = os::args();
202     let args = if os::getenv("RUST_BENCH").is_some() {
203         vec!(~"", ~"200000")
204     } else if args.len() <= 1u {
205         vec!(~"", ~"600")
206     } else {
207         args.move_iter().collect()
208     };
209
210     let nn = from_str::<uint>(*args.get(1)).unwrap();
211
212     print_complements();
213     println!("");
214
215     rendezvous(nn, vec!(Blue, Red, Yellow));
216     println!("");
217
218     rendezvous(nn,
219         vec!(Blue, Red, Yellow, Red, Yellow, Blue, Red, Yellow, Red, Blue));
220 }