]> git.lizzy.rs Git - rust.git/blob - src/test/bench/shootout-chameneos-redux.rs
doc: remove incomplete sentence
[rust.git] / src / test / bench / shootout-chameneos-redux.rs
1 // The Computer Language Benchmarks Game
2 // http://benchmarksgame.alioth.debian.org/
3 //
4 // contributed by the Rust Project Developers
5
6 // Copyright (c) 2012-2014 The Rust Project Developers
7 //
8 // All rights reserved.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions
12 // are met:
13 //
14 // - Redistributions of source code must retain the above copyright
15 //   notice, this list of conditions and the following disclaimer.
16 //
17 // - Redistributions in binary form must reproduce the above copyright
18 //   notice, this list of conditions and the following disclaimer in
19 //   the documentation and/or other materials provided with the
20 //   distribution.
21 //
22 // - Neither the name of "The Computer Language Benchmarks Game" nor
23 //   the name of "The Computer Language Shootout Benchmarks" nor the
24 //   names of its contributors may be used to endorse or promote
25 //   products derived from this software without specific prior
26 //   written permission.
27 //
28 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32 // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 // OF THE POSSIBILITY OF SUCH DAMAGE.
40
41 // no-pretty-expanded
42
43 use self::Color::{Red, Yellow, Blue};
44 use std::sync::mpsc::{channel, Sender, Receiver};
45 use std::fmt;
46 use std::str::from_str;
47 use std::thread::Thread;
48
49 fn print_complements() {
50     let all = [Blue, Red, Yellow];
51     for aa in all.iter() {
52         for bb in all.iter() {
53             println!("{} + {} -> {}", *aa, *bb, transform(*aa, *bb));
54         }
55     }
56 }
57
58 enum Color {
59     Red,
60     Yellow,
61     Blue,
62 }
63
64 impl Copy for Color {}
65
66 impl fmt::Show for Color {
67     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68         let str = match *self {
69             Red => "red",
70             Yellow => "yellow",
71             Blue => "blue",
72         };
73         write!(f, "{}", str)
74     }
75 }
76
77 struct CreatureInfo {
78     name: uint,
79     color: Color
80 }
81
82 impl Copy for CreatureInfo {}
83
84 fn show_color_list(set: Vec<Color>) -> String {
85     let mut out = String::new();
86     for col in set.iter() {
87         out.push(' ');
88         out.push_str(col.to_string().as_slice());
89     }
90     out
91 }
92
93 fn show_digit(nn: uint) -> &'static str {
94     match nn {
95         0 => {" zero"}
96         1 => {" one"}
97         2 => {" two"}
98         3 => {" three"}
99         4 => {" four"}
100         5 => {" five"}
101         6 => {" six"}
102         7 => {" seven"}
103         8 => {" eight"}
104         9 => {" nine"}
105         _ => {panic!("expected digits from 0 to 9...")}
106     }
107 }
108
109 struct Number(uint);
110 impl fmt::Show for Number {
111     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
112         let mut out = vec![];
113         let Number(mut num) = *self;
114         if num == 0 { out.push(show_digit(0)) };
115
116         while num != 0 {
117             let dig = num % 10;
118             num = num / 10;
119             let s = show_digit(dig);
120             out.push(s);
121         }
122
123         for s in out.iter().rev() {
124             try!(write!(f, "{}", s))
125         }
126         Ok(())
127     }
128 }
129
130 fn transform(aa: Color, bb: Color) -> Color {
131     match (aa, bb) {
132         (Red,    Red   ) => { Red    }
133         (Red,    Yellow) => { Blue   }
134         (Red,    Blue  ) => { Yellow }
135         (Yellow, Red   ) => { Blue   }
136         (Yellow, Yellow) => { Yellow }
137         (Yellow, Blue  ) => { Red    }
138         (Blue,   Red   ) => { Yellow }
139         (Blue,   Yellow) => { Red    }
140         (Blue,   Blue  ) => { Blue   }
141     }
142 }
143
144 fn creature(
145     name: uint,
146     mut color: Color,
147     from_rendezvous: Receiver<CreatureInfo>,
148     to_rendezvous: Sender<CreatureInfo>,
149     to_rendezvous_log: Sender<String>
150 ) {
151     let mut creatures_met = 0i32;
152     let mut evil_clones_met = 0;
153     let mut rendezvous = from_rendezvous.iter();
154
155     loop {
156         // ask for a pairing
157         to_rendezvous.send(CreatureInfo {name: name, color: color}).unwrap();
158
159         // log and change, or quit
160         match rendezvous.next() {
161             Some(other_creature) => {
162                 color = transform(color, other_creature.color);
163
164                 // track some statistics
165                 creatures_met += 1;
166                 if other_creature.name == name {
167                    evil_clones_met += 1;
168                 }
169             }
170             None => break
171         }
172     }
173     // log creatures met and evil clones of self
174     let report = format!("{}{}", creatures_met, Number(evil_clones_met));
175     to_rendezvous_log.send(report).unwrap();
176 }
177
178 fn rendezvous(nn: uint, set: Vec<Color>) {
179     // these ports will allow us to hear from the creatures
180     let (to_rendezvous, from_creatures) = channel::<CreatureInfo>();
181
182     // these channels will be passed to the creatures so they can talk to us
183     let (to_rendezvous_log, from_creatures_log) = channel::<String>();
184
185     // these channels will allow us to talk to each creature by 'name'/index
186     let mut to_creature: Vec<Sender<CreatureInfo>> =
187         set.iter().enumerate().map(|(ii, &col)| {
188             // create each creature as a listener with a port, and
189             // give us a channel to talk to each
190             let to_rendezvous = to_rendezvous.clone();
191             let to_rendezvous_log = to_rendezvous_log.clone();
192             let (to_creature, from_rendezvous) = channel();
193             Thread::spawn(move|| {
194                 creature(ii,
195                          col,
196                          from_rendezvous,
197                          to_rendezvous,
198                          to_rendezvous_log);
199             }).detach();
200             to_creature
201         }).collect();
202
203     let mut creatures_met = 0;
204
205     // set up meetings...
206     for _ in range(0, nn) {
207         let fst_creature = from_creatures.recv().unwrap();
208         let snd_creature = from_creatures.recv().unwrap();
209
210         creatures_met += 2;
211
212         to_creature[fst_creature.name].send(snd_creature).unwrap();
213         to_creature[snd_creature.name].send(fst_creature).unwrap();
214     }
215
216     // tell each creature to stop
217     drop(to_creature);
218
219     // print each color in the set
220     println!("{}", show_color_list(set));
221
222     // print each creature's stats
223     drop(to_rendezvous_log);
224     for rep in from_creatures_log.iter() {
225         println!("{}", rep);
226     }
227
228     // print the total number of creatures met
229     println!("{}\n", Number(creatures_met));
230 }
231
232 fn main() {
233     let nn = if std::os::getenv("RUST_BENCH").is_some() {
234         200000
235     } else {
236         std::os::args().as_slice()
237                        .get(1)
238                        .and_then(|arg| from_str(arg.as_slice()))
239                        .unwrap_or(600)
240     };
241
242     print_complements();
243     println!("");
244
245     rendezvous(nn, vec!(Blue, Red, Yellow));
246
247     rendezvous(nn,
248         vec!(Blue, Red, Yellow, Red, Yellow, Blue, Red, Yellow, Red, Blue));
249 }