]> git.lizzy.rs Git - rust.git/blob - src/test/bench/shootout-chameneos-redux.rs
28786f1e163d965898cebb37e67aad8b386ada68
[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(plugin)] 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!("{}{}", creatures_met, Number(evil_clones_met));
138     to_rendezvous_log.send(report);
139 }
140
141 fn rendezvous(nn: uint, set: Vec<Color>) {
142     // these ports will allow us to hear from the creatures
143     let (to_rendezvous, from_creatures) = channel::<CreatureInfo>();
144
145     // these channels will be passed to the creatures so they can talk to us
146     let (to_rendezvous_log, from_creatures_log) = channel::<String>();
147
148     // these channels will allow us to talk to each creature by 'name'/index
149     let mut to_creature: Vec<Sender<CreatureInfo>> =
150         set.iter().enumerate().map(|(ii, &col)| {
151             // create each creature as a listener with a port, and
152             // give us a channel to talk to each
153             let to_rendezvous = to_rendezvous.clone();
154             let to_rendezvous_log = to_rendezvous_log.clone();
155             let (to_creature, from_rendezvous) = channel();
156             spawn(proc() {
157                 creature(ii,
158                          col,
159                          from_rendezvous,
160                          to_rendezvous,
161                          to_rendezvous_log);
162             });
163             to_creature
164         }).collect();
165
166     let mut creatures_met = 0;
167
168     // set up meetings...
169     for _ in range(0, nn) {
170         let fst_creature = from_creatures.recv();
171         let snd_creature = from_creatures.recv();
172
173         creatures_met += 2;
174
175         to_creature.get_mut(fst_creature.name).send(snd_creature);
176         to_creature.get_mut(snd_creature.name).send(fst_creature);
177     }
178
179     // tell each creature to stop
180     drop(to_creature);
181
182     // print each color in the set
183     println!("{}", show_color_list(set));
184
185     // print each creature's stats
186     drop(to_rendezvous_log);
187     for rep in from_creatures_log.iter() {
188         println!("{}", rep);
189     }
190
191     // print the total number of creatures met
192     println!("{}\n", Number(creatures_met));
193 }
194
195 fn main() {
196     let nn = if std::os::getenv("RUST_BENCH").is_some() {
197         200000
198     } else {
199         std::os::args().as_slice()
200                        .get(1)
201                        .and_then(|arg| from_str(arg.as_slice()))
202                        .unwrap_or(600)
203     };
204
205     print_complements();
206     println!("");
207
208     rendezvous(nn, vec!(Blue, Red, Yellow));
209
210     rendezvous(nn,
211         vec!(Blue, Red, Yellow, Red, Yellow, Blue, Red, Yellow, Red, Blue));
212 }