Last active
August 29, 2015 14:11
-
-
Save artemkonenko/8f8035b3d37a7da0a613 to your computer and use it in GitHub Desktop.
exercise generator for students implementations of graph.algo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::os; | |
use std::rand::{task_rng, Rng}; | |
use std::cmp::min; | |
use std::char::from_u32; | |
const MIN_WORD_LEN : uint = 3; | |
const MAX_WORD_LEN : uint = 10; | |
const DROPLINE_CHANCE : uint = 100; | |
fn clean_crossword(crossword : &mut Vec<Vec<char>>) { | |
for l in range(0, crossword.len()) { | |
for c in range(0, crossword[l].len()) { | |
if crossword[l][c] == '*' { | |
crossword[l][c] = ' '; | |
} | |
} | |
} | |
} | |
fn print_crossword(crossword : &Vec<Vec<char>>) { | |
for l in range(0, crossword.len()) { | |
for c in range(0, crossword[l].len()) { | |
print!("{}", crossword[l][c]); | |
} | |
println!(""); | |
} | |
} | |
fn is_capture(crossword : &Vec<Vec<char>>, l : uint, c : uint) -> bool { | |
l < crossword.len() | |
&& c < crossword[l].len() | |
&& crossword[l][c] != '*' && crossword[l][c] != ' ' | |
} | |
fn is_apt_position(crossword : &Vec<Vec<char>>, l : uint, c : uint) -> bool { | |
crossword[l][c] == '*' | |
&& !is_capture(crossword, l-1, c-1) | |
&& !is_capture(crossword, l-1, c) | |
&& !is_capture(crossword, l-1, c+1) | |
&& !is_capture(crossword, l, c-1) | |
&& !is_capture(crossword, l, c+1) | |
&& !is_capture(crossword, l+1, c-1) | |
&& !is_capture(crossword, l+1, c) | |
&& !is_capture(crossword, l+1, c+1) | |
} | |
fn space_it(crossword : &mut Vec<Vec<char>>, l : uint, c : uint) | |
{ | |
if l < crossword.len() && c < crossword[l].len() | |
{ | |
crossword[l][c] = ' '; | |
} | |
} | |
fn find_place_for_word(crossword : &Vec<Vec<char>>, startline : uint) -> Option<(uint, (uint, uint))> { | |
let mut rng = task_rng(); | |
for l in range(startline, crossword.len()) { | |
let linelen = crossword[l].len(); | |
for c in range(0, linelen) { | |
if is_apt_position(crossword, l, c) { | |
let mut word_end = linelen-1; | |
let word_start = c; | |
for nextc in range(c+1, linelen) { | |
if !is_apt_position(crossword, l, nextc) { | |
word_end = c; | |
break; | |
} | |
} | |
if word_end != -1 { | |
if rng.gen_range(0, DROPLINE_CHANCE) == 0 { | |
break; | |
} | |
let word_len = word_end - word_start + 1; | |
if MIN_WORD_LEN <= word_len { | |
return Some((l, (word_start, word_end))) | |
} | |
} | |
} | |
} | |
} | |
None | |
} | |
fn insert_word(crossword: &mut Vec<Vec<char>>, place : (uint, (uint, uint))) { | |
let mut rng = task_rng(); | |
let word_len = min(MIN_WORD_LEN + rng.gen_range(0, MAX_WORD_LEN - MIN_WORD_LEN + 1), place.val1().1 - place.val1().0 + 1); | |
let free_space = place.val1().1 - place.val1().0 + 1 - word_len; | |
let place_shift = if free_space > 0 {rng.gen_range(0, free_space)} else {0}; | |
for wlen in range(0, word_len + 1) { | |
space_it(crossword, place.0-1, place.val1().0 + place_shift + wlen - 1); | |
space_it(crossword, place.0+1, place.val1().0 + place_shift + wlen - 1); | |
} | |
space_it(crossword, place.0, place.val1().0 + place_shift - 1); | |
space_it(crossword, place.0, place.val1().0 + place_shift + word_len); | |
for wlen in range(0, word_len) { | |
crossword[place.0][place.val1().0 + place_shift + wlen] | |
= match from_u32(rng.gen_range(0, 26) + 97) { | |
Some(x) => x, | |
None => 'a' | |
} | |
} | |
} | |
fn fill_crossword( crossword : &mut Vec<Vec<char>>, count : uint) | |
{ | |
let mut lastrow = 0; | |
for _ in range(0, count) { | |
match find_place_for_word(crossword, lastrow) { | |
Some(place) => { | |
lastrow = place.0; | |
insert_word(crossword, place) | |
}, | |
None => | |
match find_place_for_word(crossword, 0) { | |
Some(place) => { | |
lastrow = place.0; | |
insert_word(crossword, place) | |
}, | |
None => continue | |
} | |
} | |
} | |
clean_crossword(crossword); | |
} | |
fn main() { | |
let args = os::args(); | |
let size = match args.len() { | |
1 => 20, | |
_ => match from_str(args[1].as_slice()) { | |
Some(n) => n, | |
None => { | |
println!("Size must be number."); | |
return | |
} | |
} | |
}; | |
let count = match args.len() { | |
1|2 => 100, | |
_ => match from_str(args[2].as_slice()) { | |
Some(n) => n, | |
None => { | |
println!("Count must be number."); | |
return | |
} | |
} | |
}; | |
let mut crossword = Vec::from_elem(size, Vec::from_elem(size, '*')); | |
fill_crossword(&mut crossword, count); | |
print_crossword(&crossword); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment