]> git.lizzy.rs Git - rust.git/blob - src/test/bench/shootout-chameneos-redux.rs
2c8b23f2acdf1274049976cbcfbe1770c6a85436
[rust.git] / src / test / bench / shootout-chameneos-redux.rs
1 // Copyright 2012-2014 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 // no-pretty-expanded
12
13 #![feature(phase)]
14 #[phase(syntax)] extern crate green;
15
16 use std::string::String;
17 use std::fmt;
18
19 green_start!(main)
20
21 fn print_complements() {
22     let all = [Blue, Red, Yellow];
23     for aa in all.iter() {
24         for bb in all.iter() {
25             println!("{} + {} -> {}", *aa, *bb, transform(*aa, *bb));
26         }
27     }
28 }
29
30 enum Color { Red, Yellow, Blue }
31 impl fmt::Show for Color {
32     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
33         let str = match *self {
34             Red => "red",
35             Yellow => "yellow",
36             Blue => "blue",
37         };
38         write!(f, "{}", str)
39     }
40 }
41
42 struct CreatureInfo {
43     name: uint,
44     color: Color
45 }
46
47 fn show_color_list(set: Vec<Color>) -> String {
48     let mut out = String::new();
49     for col in set.iter() {
50         out.push_char(' ');
51         out.push_str(col.to_str().as_slice());
52     }
53     out
54 }
55
56 fn show_digit(nn: uint) -> &'static str {
57     match nn {
58         0 => {" zero"}
59         1 => {" one"}
60         2 => {" two"}
61         3 => {" three"}
62         4 => {" four"}
63         5 => {" five"}
64         6 => {" six"}
65         7 => {" seven"}
66         8 => {" eight"}
67         9 => {" nine"}
68         _ => {fail!("expected digits from 0 to 9...")}
69     }
70 }
71
72 struct Number(uint);
73 impl fmt::Show for Number {
74     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
75         let mut out = vec![];
76         let Number(mut num) = *self;
77         if num == 0 { out.push(show_digit(0)) };
78
79         while num != 0 {
80             let dig = num % 10;
81             num = num / 10;
82             let s = show_digit(dig);
83             out.push(s);
84         }
85
86         for s in out.iter().rev() {
87             try!(write!(f, "{}", s))
88         }
89         Ok(())
90     }
91 }
92
93 fn transform(aa: Color, bb: Color) -> Color {
94     match (aa, bb) {
95         (Red,    Red   ) => { Red    }
96         (Red,    Yellow) => { Blue   }
97         (Red,    Blue  ) => { Yellow }
98         (Yellow, Red   ) => { Blue   }
99         (Yellow, Yellow) => { Yellow }
100         (Yellow, Blue  ) => { Red    }
101         (Blue,   Red   ) => { Yellow }
102         (Blue,   Yellow) => { Red    }
103         (Blue,   Blue  ) => { Blue   }
104     }
105 }
106
107 fn creature(
108     name: uint,
109     mut color: Color,
110     from_rendezvous: Receiver<CreatureInfo>,
111     to_rendezvous: Sender<CreatureInfo>,
112     to_rendezvous_log: Sender<String>
113 ) {
114     let mut creatures_met = 0;
115     let mut evil_clones_met = 0;
116     let mut rendezvous = from_rendezvous.iter();
117
118     loop {
119         // ask for a pairing
120         to_rendezvous.send(CreatureInfo {name: name, color: color});
121
122         // log and change, or quit
123         match rendezvous.next() {
124             Some(other_creature) => {
125                 color = transform(color, other_creature.color);
126
127                 // track some statistics
128                 creatures_met += 1;
129                 if other_creature.name == name {
130                    evil_clones_met += 1;
131                 }
132             }
133             None => break
134         }
135     }
136     // log creatures met and evil clones of self
137     let report = format_strbuf!("{}{}",
138                                 creatures_met,
139                                 Number(evil_clones_met));
140     to_rendezvous_log.send(report);
141 }
142
143 fn rendezvous(nn: uint, set: Vec<Color>) {
144     // these ports will allow us to hear from the creatures
145     let (to_rendezvous, from_creatures) = channel::<CreatureInfo>();
146
147     // these channels will be passed to the creatures so they can talk to us
148     let (to_rendezvous_log, from_creatures_log) = channel::<String>();
149
150     // these channels will allow us to talk to each creature by 'name'/index
151     let mut to_creature: Vec<Sender<CreatureInfo>> =
152         set.iter().enumerate().map(|(ii, &col)| {
153             // create each creature as a listener with a port, and
154             // give us a channel to talk to each
155             let to_rendezvous = to_rendezvous.clone();
156             let to_rendezvous_log = to_rendezvous_log.clone();
157             let (to_creature, from_rendezvous) = channel();
158             spawn(proc() {
159                 creature(ii,
160                          col,
161                          from_rendezvous,
162                          to_rendezvous,
163                          to_rendezvous_log);
164             });
165             to_creature
166         }).collect();
167
168     let mut creatures_met = 0;
169
170     // set up meetings...
171     for _ in range(0, nn) {
172         let fst_creature = from_creatures.recv();
173         let snd_creature = from_creatures.recv();
174
175         creatures_met += 2;
176
177         to_creature.get_mut(fst_creature.name).send(snd_creature);
178         to_creature.get_mut(snd_creature.name).send(fst_creature);
179     }
180
181     // tell each creature to stop
182     drop(to_creature);
183
184     // print each color in the set
185     println!("{}", show_color_list(set));
186
187     // print each creature's stats
188     drop(to_rendezvous_log);
189     for rep in from_creatures_log.iter() {
190         println!("{}", rep);
191     }
192
193     // print the total number of creatures met
194     println!("{}\n", Number(creatures_met));
195 }
196
197 fn main() {
198     let nn = if std::os::getenv("RUST_BENCH").is_some() {
199         200000
200     } else {
201         std::os::args().as_slice()
202                        .get(1)
203                        .and_then(|arg| from_str(arg.as_slice()))
204                        .unwrap_or(600)
205     };
206
207     print_complements();
208     println!("");
209
210     rendezvous(nn, vec!(Blue, Red, Yellow));
211
212     rendezvous(nn,
213         vec!(Blue, Red, Yellow, Red, Yellow, Blue, Red, Yellow, Red, Blue));
214 }