]> git.lizzy.rs Git - rust.git/blob - src/test/bench/shootout-chameneos-redux.rs
Merge pull request #20510 from tshepang/patch-6
[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::thread::Thread;
47
48 fn print_complements() {
49     let all = [Blue, Red, Yellow];
50     for aa in all.iter() {
51         for bb in all.iter() {
52             println!("{} + {} -> {}", *aa, *bb, transform(*aa, *bb));
53         }
54     }
55 }
56
57 enum Color {
58     Red,
59     Yellow,
60     Blue,
61 }
62
63 impl Copy for Color {}
64
65 impl fmt::Show for Color {
66     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
67         let str = match *self {
68             Red => "red",
69             Yellow => "yellow",
70             Blue => "blue",
71         };
72         write!(f, "{}", str)
73     }
74 }
75
76 struct CreatureInfo {
77     name: uint,
78     color: Color
79 }
80
81 impl Copy for CreatureInfo {}
82
83 fn show_color_list(set: Vec<Color>) -> String {
84     let mut out = String::new();
85     for col in set.iter() {
86         out.push(' ');
87         out.push_str(col.to_string().as_slice());
88     }
89     out
90 }
91
92 fn show_digit(nn: uint) -> &'static str {
93     match nn {
94         0 => {" zero"}
95         1 => {" one"}
96         2 => {" two"}
97         3 => {" three"}
98         4 => {" four"}
99         5 => {" five"}
100         6 => {" six"}
101         7 => {" seven"}
102         8 => {" eight"}
103         9 => {" nine"}
104         _ => {panic!("expected digits from 0 to 9...")}
105     }
106 }
107
108 struct Number(uint);
109 impl fmt::Show for Number {
110     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
111         let mut out = vec![];
112         let Number(mut num) = *self;
113         if num == 0 { out.push(show_digit(0)) };
114
115         while num != 0 {
116             let dig = num % 10;
117             num = num / 10;
118             let s = show_digit(dig);
119             out.push(s);
120         }
121
122         for s in out.iter().rev() {
123             try!(write!(f, "{}", s))
124         }
125         Ok(())
126     }
127 }
128
129 fn transform(aa: Color, bb: Color) -> Color {
130     match (aa, bb) {
131         (Red,    Red   ) => { Red    }
132         (Red,    Yellow) => { Blue   }
133         (Red,    Blue  ) => { Yellow }
134         (Yellow, Red   ) => { Blue   }
135         (Yellow, Yellow) => { Yellow }
136         (Yellow, Blue  ) => { Red    }
137         (Blue,   Red   ) => { Yellow }
138         (Blue,   Yellow) => { Red    }
139         (Blue,   Blue  ) => { Blue   }
140     }
141 }
142
143 fn creature(
144     name: uint,
145     mut color: Color,
146     from_rendezvous: Receiver<CreatureInfo>,
147     to_rendezvous: Sender<CreatureInfo>,
148     to_rendezvous_log: Sender<String>
149 ) {
150     let mut creatures_met = 0i32;
151     let mut evil_clones_met = 0;
152     let mut rendezvous = from_rendezvous.iter();
153
154     loop {
155         // ask for a pairing
156         to_rendezvous.send(CreatureInfo {name: name, color: color}).unwrap();
157
158         // log and change, or quit
159         match rendezvous.next() {
160             Some(other_creature) => {
161                 color = transform(color, other_creature.color);
162
163                 // track some statistics
164                 creatures_met += 1;
165                 if other_creature.name == name {
166                    evil_clones_met += 1;
167                 }
168             }
169             None => break
170         }
171     }
172     // log creatures met and evil clones of self
173     let report = format!("{}{}", creatures_met, Number(evil_clones_met));
174     to_rendezvous_log.send(report).unwrap();
175 }
176
177 fn rendezvous(nn: uint, set: Vec<Color>) {
178     // these ports will allow us to hear from the creatures
179     let (to_rendezvous, from_creatures) = channel::<CreatureInfo>();
180
181     // these channels will be passed to the creatures so they can talk to us
182     let (to_rendezvous_log, from_creatures_log) = channel::<String>();
183
184     // these channels will allow us to talk to each creature by 'name'/index
185     let mut to_creature: Vec<Sender<CreatureInfo>> =
186         set.iter().enumerate().map(|(ii, &col)| {
187             // create each creature as a listener with a port, and
188             // give us a channel to talk to each
189             let to_rendezvous = to_rendezvous.clone();
190             let to_rendezvous_log = to_rendezvous_log.clone();
191             let (to_creature, from_rendezvous) = channel();
192             Thread::spawn(move|| {
193                 creature(ii,
194                          col,
195                          from_rendezvous,
196                          to_rendezvous,
197                          to_rendezvous_log);
198             }).detach();
199             to_creature
200         }).collect();
201
202     let mut creatures_met = 0;
203
204     // set up meetings...
205     for _ in range(0, nn) {
206         let fst_creature = from_creatures.recv().unwrap();
207         let snd_creature = from_creatures.recv().unwrap();
208
209         creatures_met += 2;
210
211         to_creature[fst_creature.name].send(snd_creature).unwrap();
212         to_creature[snd_creature.name].send(fst_creature).unwrap();
213     }
214
215     // tell each creature to stop
216     drop(to_creature);
217
218     // print each color in the set
219     println!("{}", show_color_list(set));
220
221     // print each creature's stats
222     drop(to_rendezvous_log);
223     for rep in from_creatures_log.iter() {
224         println!("{}", rep);
225     }
226
227     // print the total number of creatures met
228     println!("{}\n", Number(creatures_met));
229 }
230
231 fn main() {
232     let nn = if std::os::getenv("RUST_BENCH").is_some() {
233         200000
234     } else {
235         std::os::args().as_slice()
236                        .get(1)
237                        .and_then(|arg| arg.parse())
238                        .unwrap_or(600u)
239     };
240
241     print_complements();
242     println!("");
243
244     rendezvous(nn, vec!(Blue, Red, Yellow));
245
246     rendezvous(nn,
247         vec!(Blue, Red, Yellow, Red, Yellow, Blue, Red, Yellow, Red, Blue));
248 }