Skip to content

Instantly share code, notes, and snippets.

@artemkonenko
Last active August 29, 2015 14:11
Show Gist options
  • Save artemkonenko/8f8035b3d37a7da0a613 to your computer and use it in GitHub Desktop.
Save artemkonenko/8f8035b3d37a7da0a613 to your computer and use it in GitHub Desktop.
exercise generator for students implementations of graph.algo
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