getting rusty

It has been a little while, and I have been distracted from this project. Never the less, here is the next challenge solution; I tried to take advantage of more of the built in safety features provided by Rust, but I am still using/abusing unwrap here and there.

extern crate zip;
extern crate regex;
use std::io::Read;
use std::io::prelude::*;

fn main() {
    let args: Vec<_> = std::env::args().collect();
    if args.len() < 2 {
        println!("Usage: {} <filename>", args[0]);
        return;
    }
    let fname = std::path::Path::new(&*args[1]);
    match std::fs::File::open(fname) {
        Err(e) => panic!("file read error: {}", e),
        Ok(f) => {

            let mut archive = zip::ZipArchive::new(f).unwrap();
            
            let mut znum: i32 = 90052;
            let re = regex::Regex::new("ext nothing is ([[:digit:]]+)").unwrap();

            loop {
                let mut sub = String::new();
                let zfname = format!("{}.txt", znum.to_string());
                let response = read_zip(&mut archive, zfname);
                match re.captures(&response.as_str()) {
                    Some(c) => sub = c.get(1).map_or("0", |m| m.as_str()).to_string(),
                    None => (),
                };
                match sub.parse::<i32>() {
                    Ok(v) => znum = v,
                    Err(_) => break
                };
            }
        }
    }

}

fn read_zip<R: Read + Seek>(archive: &mut zip::read::ZipArchive<R>,
                            filename: String) -> String {
    let zf  = archive.by_name(&filename).unwrap();
    print!("{}", zf.comment());

    let zb: Vec<_> = zf.bytes().map(|b| b).filter_map(Result::ok).collect();
    let s = match std::str::from_utf8(&zb) {
        Ok(v) => v,
        Err(e) => panic!("Invalid UTF-8 sequence: {}", e),
    };
    return s.to_string()
}
Advertisements

Rust Challenge cont.

Continuing to learn rust via the python challenge. here is the solution to the next challenge…

extern crate regex;
extern crate reqwest;
#[macro_use]
extern crate error_chain;

error_chain! {
    foreign_links {
        ReqError(reqwest::Error);
        IoError(std::io::Error);
    }
}

fn nnothing(nothing:i32) -> String { 
    let req = format!("http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing={}", nothing.to_string());
    let mut res = reqwest::get( &req ).expect("failed to contact server.");
    return res.text().expect("oops. it broke. no response.");
}


fn main() {
    let re = regex::Regex::new("next nothing is ([[:digit:]]+)").unwrap(); 
    let mut nn: i32 = 12345;
    let mut max: i32 = 420;
    while nn > 0 && max > 0 {
        max -= 1;
        let mut sub: String = "".to_string();
        let rtext = nnothing(nn);
        match re.captures(&rtext.as_str()) {
            Some(c) => sub=c.get(1).map_or("0", |m| m.as_str()).to_string(),
            None => nn = nn/2
        };
        println!("'{}'", rtext.as_str());
        match sub.parse::<i32>() {
            Ok(v) => nn = v,
            Err(m) => println!("{:#?}", m)
        }; 
    }
}

Challenge

Following my dismal performance in the technical portion of an interview last week, I decided that I needed to regularly work on programming tasks in order to maintain my technical skills. Unfortunately most of the courses I have been taking have given me few opportunities to flex my coding skills, and my personal projects have been dwindling in need of attention. Without a current project to work on, I decided to go back to the pythonchallenge buth this time, trying Rust, which is new to me. However, while rust is capable of fairly low level access, it just doesn’t scratch the same itch as C, so after the first couple of challenges, I decided to try to solve one in C.

First, in Rust; opne a file of garbage and sort out the lower-case letters:

use std::io::BufReader;
use std::io::BufRead;
use std::fs::File;

fn main() 
{
        let f = File::open("garbage.txt").unwrap();
        let file = BufReader::new(&f);
        for line in file.lines() 
        {
                let l = line.unwrap();
                for c in l.as_bytes() 
                {
                print!("{}", if (*c as char).is_alphanumeric() { 
                                                 *c as char} else {0 as char});
                } 
        }
        print!("\n");
}       

And then the same problem solved in pure C:

#include<stdio.h>


int main( void ) {
        static const char filename[] = "garbage.txt";
        FILE *file = fopen ( filename, "r" );
        if ( file != NULL )
        {
        char line [ 128 ];
                while ( fgets ( line, sizeof line, file ) != NULL )
                {
                        for (int i=0; i<sizeof line; i++){
                                if (line[i] > 96 && line[i] < 123)
                                {
                                        printf("%c",line[i]);
                                } 
                        }
      }
      printf("\n");
      fclose ( file );
   }
   else
   {
      perror ( filename );
   }
   return 0;
}       

They are probably both horribly hacky, but they both do the job. I will try to continue this in the weeks ahead.

Edit:

I was intrigued by the performance differences between these two solutions, so I did a little testing and found that the hacky c solution scans 1250 lines of the input text in 0.005 seconds while the rust solution takes 1.282 seconds. This inspired me to write a c version that used a regex like the rust solution does:

#include<stdio.h>
#include<regex.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>


int find(char * pattern, char * input  ) {
  regex_t regex;
  int reti;
  reti = regcomp(&regex, pattern, REG_EXTENDED);
  regmatch_t matches[2];
  char result [ 9 ];
  int search;
  /* Execute regular expression */
    search = regexec(&regex, input, 2, matches, 0);
    if (search == REG_NOMATCH) {}
    else {
      for (int i = 0; matches[i].rm_so != -1; i++)
      {
        int len = matches[i].rm_eo - matches[i].rm_so;
        memcpy(result, input + matches[i].rm_so + 4, 1);
        result[len] = 0;
        printf("%s",result);
      }
      regfree(&regex);
      return 0;
    }

}

// a C regex solution
int main( void ) {
  char line [ 128 ];
        static const char filename[] = "garbage2.txt";
        FILE *file = fopen ( filename, "r" );
        if ( file != NULL )
        {
    char pattern[] = "[a-z][A-Z]{3}[a-z][A-Z]{3}[a-z]";
                while ( fgets ( line, sizeof line, file ) != NULL )
                {
      find(pattern, line);
    }
    fclose ( file );
    printf("\n");
   }
   else
   {
      perror ( filename );
   }
   return 0;
}

The c solution with regex is still significantly faster than rust clocking in 0.044 seconds. Then, I was inspired by a friend to try to optimize the plain c version further, using bit-masking as tool pattern match multiple chars at a time. This was slightly problematic since the pattern is nine chars long, and a long long can only mask 8 chars; the solution was to pattern match the first 8 chars of the pattern with one bitmask, then use another smaller bitmask to check the final char in the pattern. Unfortunately this yielded no improvement over the original, clunkier version.

#include<stdio.h>

int main( void ) {
        static const char filename[] = "garbage2.txt";
        FILE *file = fopen ( filename, "r" );
        if ( file != NULL )
        {
        char line [128];
                while ( fgets ( line, sizeof line, file ) != NULL )
                {
                        char c;
                        char *in = line;
                        long long int test = 0;
                        long long int p1 = 0x2020202020202020;
                        long long int p2 = 0x2000000020;
                        for (int i=0; i<sizeof(line) - 9; i++){
                                c = in[4];
                                test = in[0] | (in[1] << 8) | (in[2] << 16) | (in[3] << 24) | ((long long) in[4] << 32) | ((long long) in[5] << 40) | ((long long) in[6] << 48) | ((long long) in[7] << 56);
                                long long int m = test & p1;
                                test = m ^ p2;
                                int test2 = (int)in[8] & 0x20;
                                if ((!test) && (test2)){
                                        printf("%c", c );
                                }
                                in = &in[1];
                        }
   }
         printf("\n");
     fclose ( file );
   }
   else
   {
      perror ( filename );
   }
   return 0;
}

 

Reviving a Clickfree backup drive with dd

Visiting family over the holidays of course means tuning up various computers; converting one over to linux, and doing standard OS maintenance on another. While cleaning up the system on my mothers computer, she explained that she missed her clickfree backup; following a report of disk errors, it had requested retirement, and so it was replaced by a MyPassport drive. However, it was not as simple to use as the old clickfree drive it had replaced; a common complaint from former owners of clickfree drives. Continue reading

TicTacToe

I thought that now that I am back in a couple of programming courses, I would be posting here more often. However, most of the course work I end up doing is pretty tame, and not really worth writing about. But I finally ran into a fun little puzzle with the tic-tac-toe challenge. Not with the game of course, but with the AI. It is easy enough make an AI that cannot be beat, but I wanted to make one that would intelligently try to win as well. I went with a move-weight model, scanning every possible move adding up weights, and then taking the highest weighted move.

The following is the code for the AI;

Continue reading

a better date range picker

I was unhappy with the range-datepickers I had seen so I made my own. I needed a date range picker that could select ranges of years, quarters or months, and I couldn’t find one that worked in this way. I had been using the jquery datepicker, but it didn’t have a “quarter” option; although it may have been possible to extend the datepicker to allow for this. at any rate, this is still a little rough and a little long in the code, but it works the way I wanted it to; the available months/quarters and years change in logical ways depending on the current selection in each of the other select menus. It also preserves the selected date through aggregate mode changes; a setting of March is still there when switched to “quarterly mode” and back to “monthly mode”.

date-range-picker
the date-range-picker in Google Chrome

Here’s the date-range-picker in chrome; appearance will vary depending on the browser and the implemented formating. This may be a reason to switch over to hidden select elements mirrored by styled divs in order to have cross-browser consistency and for increased visual adaptability.

Continue reading

netbeans 7.0.1 is broken

I just spent way too much time figuring out that Netbeans 7.0.1 (from the repos) is broken. If anybody else is struggling with it, stop and upgrade to the 7.1.2 version at netbeans.org. In particular, it was silently failing to integrate with Mercurial. Additionally, many of the configuration dialogs were malfunctioning. Hopefully this helps somebody.