Quantcast
Channel: 懒得折腾
Viewing all 764 articles
Browse latest View live

What’s new with JavaScript and geospatial – wrapup from the js.geo event

$
0
0

What’s new with JavaScript and geospatial – wrapup from the js.geo event

 
The past couple of days I’ve been at the js.geo event in Denver, which was a small informal conference focused on JavaScript and geospatial, organized by Chris Helm, Steve Citron-Pousty and Brian Timoney. I’ve been head down on customer projects and product development the past few months, so it was great to get out and see what’s going on in the broader world. As usual with this type of event I was blown away by how much cool new stuff people are doing – it’s definitely a tough job to keep up with everything that’s going on these days! The attendees included a great cross-section of people involved with the major geospatial JavaScript projects. I’ve said this before, but increasingly I find that informal “unconference” style events, which are either free or very cheap (this one had a registration fee of $11.54!) provide an experience that is just as good as, if not better than, the larger, more expensive and more organized conferences.

My brain is overflowing at the end of the two days, and I have lots of things I want to look into more. This post is mainly a list of items I found interesting with some links. Apologies in advance to anyone / anything I missed out! Without further ado …

D3

D3 is a very cool general purpose JavaScript interactive visualization library, developed by Mike Bostock, that includes some good (mainly vector) geospatial capabilities. This was probably the hottest topic at the conference, lots of people talking about it and incorporating it into demos. Here’s a blog post from CartoDB with some examples. D3 supports a new format calledTopoJSON, which is similar to geoJSON, but supports topology to eliminate redundancy. For polygon data this can reduce data volumes by around 80% (compared to regular geoJSON). It also lends itself to robust simplification of polygons

LEAFLET

Several presentations, including this one by Aaron Ogle, confirmed the impression I had that the Leaflet JavaScript mapping API has great momentum. Matt Priour in his presentation on OpenLayers acknowledged as much with his pitch that OpenLayers was “almost as convenient as Leaflet and twice as powerful”. One of the key selling points of Leaflet is its simplicity. Matt said that in discussions about OpenLayers 3 there were proponents of just moving to adopt Leaflet instead of doing a major redevelopment of OpenLayers, but it was decided for various reasons that OpenLayers 3 was needed – you can see further discussion on its aims here. It’s important to be aware that OpenLayers 3 will not be compatible with OpenLayers 2, it’s going to be a fresh start. We are looking seriously at using Leaflet for a future version of our Ubisense myWorld application.

CARTODB

I continue to be very impressed with CartoDB. They first launched the product at FOSS4G in Denver in 2011, and released Version 2 in November 2012, with lots of cool new features. These include a new system called Torque which does beautiful spatio-temporal visualizations, and new density maps using either hexagons or squares. I definitely plan to work on including CartoDB in the solutions that we’re offering. Check out Andrew Hill’s presentation.

MAPSTRACTION

Andrew Turner gave a lightning talk about Mapstraction, a library that provides an abstraction layer for the major mapping APIs. Last time I looked at this I had the impression it wasn’t being very actively developed, but it seems I was misinformed! This is something I want to investigate further too. There’s a nice sandbox demo site here.

MAPBOX 

The folks at MapBox also continue to do a whole range of interesting things, from their TileMill map rendering product to a range of map sharing tools at Mapbox.com to their iPad application. A little while ago I did a simple demo with some utility data using various bits of MapBox infrastructure, borrowing heavily from this example (you’ll probably need a browser other than Internet Explorer for these to work). As well as giving a workshop, Will White talked about their server side architecture which uses node.js (JavaScript on the server).

UBISENSE MYWORLD

I did a short presentation and demo on what we’re up to with Ubisense myWorld, building web applications for utilities and telecoms using Google Maps and various open source products. I’ll do a longer post soon on what we’ve been up to recently, but we got some good interest in what we’ve done with Google Street View, including the overlay of linear objects like gas pipes, and also in work we did to help a customer with recovery efforts after Hurricane Sandy. Thanks to Steve Citron-Pousty for his summary:

WEBGL

Brendan Kenny from Google gave an interesting talk on WebGL, which brings high performance 3D (and 2D) graphics to (most) web browsers (no prizes for guessing which one is the main exception!). He did a really impressive demo that involved displaying very large numbers of points in the browser with dynamic charts based on the current map window and dynamic filtering tools.

MISCELLANEOUS OTHER LINKS

In no particular order …

npm is “Node Packaged Modules” which was highly recommended by Will White for managing either server side or client side JavaScript Code.

openweathermap.org is a cool resource for free and open weather data.

Backbone.js and Marionette.js, which builds on top of Backbone, were highly recommended by Dave Bouwman as frameworks for building complex JavaScript applications. I definitely plan to look more at these for what we’re doing. Ember.js was also mentioned as an alternative.

Max Ogden’s geoJSON utilities got several mentions, a lightweight JavaScript library that supports some core spatial operations like point in polygon, distance and more on geoJSON data.

The Google Visualization API looks like a nice library for visualizing data tables and charts.

PhantomJS is a headless webkit browser that is useful for various things including browser screen capture and testing. This blog post talks about using it to implement a web map printing tool. Alfred Sawatzky talked about how he used this to capture periodic screen shots of his company iFactor’s outage maps during the Hurricane Sandy recovery.

Rickshaw.js is a JavaScript toolkit for creating interactive time series graphs.

The ESRI CityEngine Web Viewer is a cool application for viewing 3D city models in a browser without any plugins. You can see various examples here, press the play button at the bottom left for an automated tour of a model. This one in Philadelphia is impressive.

Simtable are doing interesting things with projecting animated data onto 3D models.

MongoDB is a scalable open source NoSQL database that provides geospatial support – up until now just for points, but about to have support for any geoJSON geometry and operations like point in polygon etc. Steve Citron-Pousty ran a workshop on this which I would have liked to have gone to, but I went to the MapBox / CartoDB one instead.

So, lots of things to research and absorb!!

UpdateTyler Burgett also shared some excellent detailed notes, and Steve C-P has posted agood summary too.



Design and Analysis of Algorithm 2 Homework 6

$
0
0

Question 1

In this assignment you will implement one or more algorithms for the 2SAT problem. Here are 6 different 2SAT instances: #1 #2 #3 #4 #5 #6.The file format is as follows. In each instance, the number of variables and the number of clauses is the same, and this number is specified on the first line of the file. Each subsequent line specifies a clause via its two literals, with a number denoting the variable and a “-” sign denoting logical “not”. For example, the second line of the first data file is “-16808 75250″, which indicates the clause ¬x16808∨x75250.

Your task is to determine which of the 6 instances are satisfiable, and which are unsatisfiable. In the box below, enter a 6-bit string, where the ith bit should be 1 if the ith instance is satisfiable, and 0 otherwise. For example, if you think that the first 3 instances are satisfiable and the last 3 are not, then you should enter the string 111000 in the box below.

DISCUSSION: This assignment is deliberately open-ended, and you can implement whichever 2SAT algorithm you want. For example, 2SAT reduces to computing the strongly connected components of a suitable graph (with two vertices per variable and two directed edges per clause, you should think through the details). This might be an especially attractive option for those of you who coded up an SCC algorithm for Part I of this course. Alternatively, you can use Papadimitriou’s randomized local search algorithm. (The algorithm from lecture might be too slow; but perhaps there are some simple ways to ensure that it doesn’t run too long?) A third approach is via backtracking. In lecture we mentioned this approach only in passing; see the DPV book, for example, for more details.

 

import fileinput
import networkx as nx
#import number_strongly_connected_components from nx
i = 0
for i in range(1, 7):
	G=nx.DiGraph()
	k = 0
	for line in fileinput.input("2sat" + str(i) + ".txt"):
		k = k + 1
		if (k == 1):
			M = int(line)	
			continue	
		words = line.strip().split(" ")
		start = int(words[0].strip())
		end = int(words[1].strip())
		G.add_node(start)
		G.add_node(end)
		G.add_node(-start)
		G.add_node(-end)
		G.add_edge(-start,end)
		G.add_edge(-end,start)
	#print len(G.nodes())
	#print len(G.edges())
	resultList = nx.kosaraju_strongly_connected_components(G)
	strResult = "Success"
	for l in resultList:
		if(len(l) > 1):
			print l
			for x in l:
				for y in l:
					if (x == y):
						continue
					if (x == -y):
						strResult = "Failed"
	print str(i) + ": " + strResult


Programming Languages Programming Assignment 2

$
0
0

Code

(* Dan Grossman, Coursera PL, HW2 Provided Code *)

(* if you use this function to compare two strings (returns true if the same
   string), then you avoid several of the functions in problem 1 having
   polymorphic types that may be confusing *)
fun same_string(s1 : string, s2 : string) =
    s1 = s2

(* put your solutions for problem 1 here *)
fun all_except_option (str : string, xs : string list) = 
   let
     fun isInside (xs : string list) = 
        case xs of 
           [] => false
         | x::xs' => if same_string(str,x) then true
                     else isInside(xs') 
     fun all_except_option_help (xs : string list, ys: string list) = 
         case xs of
           [] => ys
          | x::xs' => if same_string(str, x) then all_except_option_help (xs', ys)
                                            else all_except_option_help (xs', ys@[x])
   in
     case isInside(xs) of 
       false => NONE
      | true  => SOME(all_except_option_help(xs, []))  
   end
fun get_substitutions1 (strlistlist : string list list, s : string ) = 
  case strlistlist of 
     [] => []
   | strlist::strlistlist' => let
                                 val res = all_except_option (s, strlist)
                              in
                                 case res of
                                    NONE => get_substitutions1 (strlistlist', s)
                                  | SOME reslist  => reslist @ get_substitutions1 (strlistlist', s) 
                              end
 fun get_substitutions2 (strlistlist : string list list, s : string ) = 
    let fun  get_substitutions2_helper (strlistlist : string list list, acc : string list) = 
           case strlistlist of 
              [] => acc
	    | strlist::strlistlist' => let
                                 val res = all_except_option (s, strlist)
                              in
                                 case res of
                                    NONE => get_substitutions2_helper (strlistlist', acc)
                                  | SOME reslist  => get_substitutions2_helper (strlistlist', acc@reslist) 
                              end
    in
        get_substitutions2_helper (strlistlist, [])
    end
 fun similar_names (strlistlist : string list list, fullname : {first:string, middle:string, last:string} ) =
    let val {first=x, middle=y, last=z} = fullname
        val firstnamelist = get_substitutions2 (strlistlist, x)
        fun similar_names_helper (firstnamelist : string list, fullnamelist : {first:string, last:string, middle:string} list) = 
            case firstnamelist of
                [] => fullnamelist
		   | firstname::firstnamelist' => similar_names_helper(firstnamelist', fullnamelist @ [ {first = firstname, last = z, middle = y}])
    in
        similar_names_helper(firstnamelist, [{first = x, last = z, middle = y}])
    end

(* you may assume that Num is always used with values 2, 3, ..., 9
   though it will not really come up *)
datatype suit = Clubs | Diamonds | Hearts | Spades
datatype rank = Jack | Queen | King | Ace | Num of int 
type card = suit * rank

datatype color = Red | Black
datatype move = Discard of card | Draw 

exception IllegalMove

(* put your solutions for problem 2 here *)
fun card_color (c : card ) = 
   let val (s, r) = c
   in
      case s of
         Spades => Black
       | Clubs  => Black
       | Diamonds => Red
       | Hearts  => Red   
   end
fun card_value (c : card ) = 
   let val (s, r) = c
   in
      case r of
         Ace => 11
       | Jack  => 10
       | Queen => 10
       | King  => 10
       | Num(num) => num   
   end

fun remove_card (cs : card list, c: card, e) =  
   let
     fun isInside (xs : card list) = 
        case xs of 
           [] => false
         | x::xs' => if x = c then true
                     else isInside(xs') 
     fun remove_card_helper (xs : card list, result : card list) = 
        case xs of
           [] => result
          | x::xs' => if (c = x) then result @ xs' else remove_card_helper(xs', result @ [x])   
  in
    if (isInside(cs)) then remove_card_helper (cs, [])
                      else raise e
  end
fun all_same_color (cs : card list) =  
    case cs of
       [] => true
     | _::[] => true
     | head :: (neck :: rest) => ((card_color(head) = card_color(neck)) andalso all_same_color(neck :: rest))
fun sum_cards (cs : card list) = 
    let fun sum_cards_helper (cs : card list, acc : int) = 
          case cs of
             [] => acc
           | c::cs' => sum_cards_helper(cs', acc + card_value(c))
    in
       sum_cards_helper(cs, 0)
    end  
fun score (cs : card list, goal : int) = 
    let
       val s = sum_cards (cs)
       val pScore = if (s > goal) then 3*(s - goal) else (goal - s)
       val result = if (all_same_color(cs)) then (pScore div 2) else pScore     
    in
        result
    end

fun officiate (cardlist : card list, movelist : move list, goal : int) = 
    let
      fun officiate_helper (cardlist : card list, movelist : move list, heldcards : card list) =
          case movelist of
             [] => heldcards
	    | move::movelist' => case move of 
                                    Draw => ( case cardlist of
                                               [] => heldcards
					       | card::cardlist'  => if (sum_cards (card :: heldcards) > goal) 
                                                                     then card :: heldcards 
                                                                     else officiate_helper(cardlist', movelist', card :: heldcards)
                                             )
			            | Discard c => remove_card(heldcards, c, IllegalMove)
    in
        score(officiate_helper (cardlist, movelist, []), goal)
    end

Test Cases

(* Dan Grossman, Coursera PL, HW2 Provided Tests *)

(* These are just two tests for problem 2; you will want more.

   Naturally these tests and your tests will use bindings defined 
   in your solution, in particular the officiate function, 
   so they will not type-check if officiate is not defined.
 *)

fun provided_test1 () = (* correct behavior: raise IllegalMove *)
    let val cards = [(Clubs,Jack),(Spades,Num(8))]
	val moves = [Draw,Discard(Hearts,Jack)]
    in
	officiate(cards,moves,42)
    end

fun provided_test2 () = (* correct behavior: return 3 *)
    let val cards = [(Clubs,Ace),(Spades,Ace),(Clubs,Ace),(Spades,Ace)]
	val moves = [Draw,Draw,Draw,Draw,Draw]
    in
 	officiate(cards,moves,42)
    end
 val  all_except_option_test = all_except_option("a", ["b","c","d","e","f"]);
 val get_substitutions1_test = get_substitutions2([["Fred","Fredrick"],["Elizabeth","Betty"],["Freddie","Fred","F"]],"Fred");
 val get_substitutions1_test = get_substitutions2([["Fred","Fredrick"],["Jeff","Jeffrey"],["Geoff","Jeff","Jeffrey"]],"Jeff");
 val similar_names_test = similar_names([["Fred","Fredrick"],["Elizabeth","Betty"],["Freddie","Fred","F"]],{first="Fred", middle="W", last="Smith"});
 val card_color_test = card_color((Clubs,Jack));
 val card_value_test = card_value((Clubs,Jack));
 val cards = [(Clubs,Jack),(Spades,Num(8))]
 val remove_card_test = remove_card ([(Clubs,Jack),(Spades,Num(8))], (Spades,Num(7)), IllegalMove);
 val all_same_color_test = all_same_color([(Clubs,Jack),(Spades,Num(8))]);
 val sum_cards_test = sum_cards([(Clubs,Jack),(Spades,Num(8))]);
 val score_test = score([(Clubs,Jack),(Spades,Num(8))], 10);
 

JavaScript and CSS dynamic loading

$
0
0
globalConfig.loadCSS = globalConfig.loadCSS || function(filename){
	var fileref=document.createElement("link");
	fileref.setAttribute("rel", "stylesheet");
	fileref.setAttribute("type", "text/css");
	fileref.setAttribute("href", filename);
	document.getElementsByTagName("head")[0].appendChild(fileref);
};

globalConfig.loadScript = globalConfig.loadScript || function(url, callback){
	var script = document.createElement('script');
	script.type = "text/javascript";
	if(script.readyState){
		script.onreadystatechange = function(){
			if(script.readyState === "loaded" || script.readyState === "complete"){
				script.onreadystatechange = null;
				callback();
			}
		};
	}else{
		script.onload = function(){
			callback();
		};
	}	
	script.src = url;
	document.getElementsByTagName("head")[0].appendChild(script);
};

Batch Geonews: From ArcMap to MapBox, Esri GeoDatabases, China Mandates Beidou, and more

$
0
0

Here’s the recent geonews in batch mode.

From the open source front:

From the Esri front:

From the Google front:

In the miscellaneous category:

In the maps category:


Batch Geonews: Landsat 5 Decommissioned, GeoPackage RFC, Geocoding Client API in GDAL/OGR, Drone Stories, and much more

$
0
0

This is an abnormally long version of our ‘batch geonews’ edition, covering the news since the holiday break.

On the open source & open data front:

On the Esri front:

In the miscellaneous category:

A bunch of minor geo-related stories discussed over Slashdot:

In the maps category:


Programming Languages Programming Assignment 3

$
0
0

Code

(* Coursera Programming Languages, Homework 3, Provided Code *)

exception NoAnswer

datatype pattern = Wildcard
		 | Variable of string
		 | UnitP
		 | ConstP of int
		 | TupleP of pattern list
		 | ConstructorP of string * pattern

datatype valu = Const of int
	      | Unit
	      | Tuple of valu list
	      | Constructor of string * valu

fun g f1 f2 p =
    let 
	val r = g f1 f2 
    in
	case p of
	    Wildcard          => f1 ()
	  | Variable x        => f2 x
	  | TupleP ps         => List.foldl (fn (p,i) => (r p) + i) 0 ps
	  | ConstructorP(_,p) => r p
	  | _                 => 0
    end


(**** for the challenge problem only ****)

datatype typ = Anything
	     | UnitT
	     | IntT
	     | TupleT of typ list
	     | Datatype of string

(**** you can put all your code here ****)
fun only_capitals (xs : string list) = 
    List.filter (fn x => Char.isUpper(String.sub(x, 0))) xs;
fun longest_string1 (xs : string list) = 
    let 
	   fun longest_string1_helper xs acc = 
         case xs of 
	       [] => acc
	        | x::xs' => if (String.size(x) > String.size(acc)) then longest_string1_helper xs' x else longest_string1_helper xs' acc;
	in 
	    longest_string1_helper xs ""
	end;
fun longest_string2 (xs : string list) = 
    let 
	   fun longest_string2_helper xs acc = 
         case xs of 
	       [] => acc
	        | x::xs' => if (String.size(x) >= String.size(acc)) then longest_string2_helper xs' x else longest_string2_helper xs' acc;
	in 
	    longest_string2_helper xs ""
	end;
fun longest_string_helper f xs = 
    let 
	   fun longest_string_helper1 f xs acc = 
         case xs of 
	       [] => acc
	        | x::xs' => if f(String.size(x), String.size(acc)) then longest_string_helper1 f xs' x else longest_string_helper1 f xs' acc;
	in 
	    longest_string_helper1 f xs ""
	end;
val longest_string3 = longest_string_helper(fn (x,y) => if ( x > y) then true else false );
val longest_string4 = longest_string_helper(fn (x,y) => if ( x >= y) then true else false);
val longest_capitalized = longest_string1 o only_capitals;
val rev_string = implode o rev o explode;
fun first_answer f xs = 
    case xs of 
      []    => raise NoAnswer
     | x::xs'  => case f(x) of
              NONE => first_answer f xs'
              | SOME(v)  => v 

fun all_answers f xs = 
    let 
       fun all_answers_helper xs acc = 
	       case xs of 
             []    => SOME(acc)
            | x::xs'  => case f(x) of
                   NONE => NONE
                   | SOME(lst)  => all_answers_helper xs' (acc @ lst)
	in 
       all_answers_helper xs []
	end
fun count_wildcards p = g (fn () => 1) (fn (x) => 0) p;
fun count_wild_and_variable_lengths p = g (fn () => 1) (fn (x) => String.size(x)) p;
fun count_some_var (s : string, p : pattern) = 
    g (fn () => 0) (fn (x) => if ( x = s) then 1 else 0) p;
fun check_pat (p : pattern) = 
    let
	   fun getStrings (p : pattern) = 
			case p of
				Wildcard          => []
			  | Variable x        => [x]
			  | TupleP ps         => List.foldl (fn (p,i) => getStrings(p) @ i) [] ps
			  | ConstructorP(_,p) => getStrings (p)
			  | _                 => []	        
	    fun duplicated (xs : string list) =
                case xs of
                  [] => false
              | x::xs' => (List.exists (fn y => x = y) xs') orelse (duplicated xs')
	in
	   not ( duplicated(getStrings (p)))
	end
fun match (v : valu, p : pattern) = 
	case p of
	    Wildcard            => SOME([])
	  | Variable s          => SOME([(s, v)])
	  | UnitP               => if (v = Unit) then SOME([]) else  NONE 
	  | ConstP x            => ( case v of 
	                           Const y => if (x = y) then SOME([]) else NONE
                      	          | _      => NONE)
	  | TupleP ps           => ( case v of 
	                           Tuple vs => (if (List.length(ps) = List.length(vs)) then (all_answers match (ListPair.zip(vs, ps))) else NONE)
                                  | _       => NONE ) 
	  | ConstructorP(s1,p1) => (case v of 
	                            Constructor(s2, v1) => if (s1 = s2) then match (v1, p1) else NONE
                                  | _                   => NONE )
fun first_match	v plst = 
	      SOME(first_answer (fn (p) => match(v, p)) plst) handle NoAnswer => NONE

Tests

(* turn off obnoxious warning about calling polyEqual *)
(* hopefully, we know what we're doing ;)              *)
val _ = Control.polyEqWarn := false;

val _ = let
    (* utility *)
    fun printResults(results) = foldl (fn ((module, report), _) => print(module ^ ":\n" ^ report ^ "\n")) () results
    fun allStringsEqual str strs = foldl (fn (nextStr, allEqualSoFar) => allEqualSoFar andalso nextStr = str) true strs
    fun onlyFailedModules results =
        List.map
            (fn (module, result) => (module, foldl (op ^) "" result))
            (List.filter (fn (_, result) => (not o (allStringsEqual "")) result) results)

    (* assertion framework *)
    fun assert(msg: string, e: bool) = if e then "" else "\tFAIL: " ^ msg ^ "\n"
    fun assertFalse(msg: string, e: bool) = assert(msg, not e)
    fun assertEquals(msg, expected, result) = assert("expected " ^ msg, expected = result)
    fun assertEqualsInt(msg, expected, result) =
        assertEquals("int " ^ Int.toString(expected) ^ " but was " ^ Int.toString(result) ^ " - " ^ msg, expected, result)
    fun assertEmptyList(msg, xs) = assert("expected empty list - " ^ msg, null xs)
    fun assertEqualsList(msg, expected, result) = assertEquals("equal lists - " ^ msg, expected, result)
    fun assertEqualsString(msg, expected, result) =
        assertEquals("string '" ^ expected ^ "' but was '" ^ result ^ "' - " ^ msg, expected, result)
    fun assertNone(msg: string, result) = assert("expected NONE but got SOME - " ^ msg, not (isSome result))
    fun assertSome(msg, expected) = assert("expected SOME but got NONE - " ^ msg, isSome(expected))

    (* tests *)
    (* TODO: should implement `test` runner (only feasible with some kind of lazy evaluation scheme) *)
    (*       (also setup/teardown functions, number of tests run, ...)                             *)
    (*       consider passing the function to be tested as a parameter just once, to avoid         *)
    (*       having to repeat the function name all the time                                       *)
    (*       find out if SML allows the code to find out a function name as a string, to avoid     *)
    (*       having to pass the `test` function both as a symbol and as a string                     *)
    val tests = [
        ("only_capitals", [
            assertEmptyList("for empty list", only_capitals([])),
            assertEqualsList("for list with uppercase strings", ["Upper", "Case"],
                only_capitals(["lower", "case", "Upper", "Case"])
            )
        ]),
        ("longest_string1", [
            assertEqualsString("for 'longest' as the first of many longest strings",
                "longest", longest_string1(["short", "small", "longest", "tiny", "l0ng3st"]))
        ]),
        ("longest_string2", [
            assertEqualsString("for 'l0ng3st' as the last of many longest strings",
                "l0ng3st", longest_string2(["short", "small", "longest", "tiny", "l0ng3st"]))
        ]),
        ("longest_string_helper", let
            fun like_in_longest_string_1(x, y) = x > y
        in [
            assertEqualsString("for 'longest' as the first of many longest strings",
                "longest", longest_string_helper like_in_longest_string_1 ["short", "small", "longest", "tiny", "l0ng3st"])
        ] end),
        ("first_answer", [
            assert("should raise NoAnswer for empty list",
                (* NOTE: sort of tedious construct to `test` for the right kind of exception to be raised *)
                (*       maybe figure out a more elegant way                                            *)
                (*       trivial, if lazy evaluation is possible in any way                             *)
                case SOME(SOME(first_answer (fn x => NONE) [])) handle NoAnswer => NONE | _ => SOME(NONE) of
                    NONE => true
                    | SOME _ => false
            ),
            assertEqualsInt("for equals_3 on increasing list", 3,
                first_answer (fn x => case x of 3 => SOME 3 | _ => NONE) [1, 2, 3, 4, 5]
            )
        ]),
        ("all_answers", [
            assertEquals("for any f and empty list", SOME [], all_answers (fn x => x) []),
            assertNone("for x => NONE and any list", all_answers (fn x => NONE) [1, 2, 3, 4, 5]),
            assertEqualsList("for x => SOME [x, x*x] and an int list", SOME [2, 4, 5, 25, 3, 9, 4, 16],
                all_answers (fn x => SOME [x, x*x]) [2, 5, 3, 4]
            )
        ]),
        ("count_wildcards", [
            assertEqualsInt("for tuple of Wildcard patterns", 3,
                count_wildcards (TupleP [Wildcard, ConstP 3, Wildcard, UnitP, Wildcard]))
        ]),
        ("check_pat", [
            assertFalse("for repeated Variable name", check_pat (TupleP [Variable "my_var", Variable "my_var"])),
            assertFalse("for repeated Variable names with other patterns interspersed",
                check_pat(TupleP [Variable "my_var", UnitP, Wildcard, Variable "my_var"])
            ),
            assert("for non-repeated Variables names with other patterns interspersed",
                check_pat (TupleP [Variable "my_var", UnitP, Wildcard, Variable "other_var"])
            )
        ]),
        ("match", [
            assertEquals("empty binding list for Wildcard pattern", SOME [], match(Const 16, Wildcard)),
            assertEquals("one binding for matching pattern with one Variable", SOME [("my_var", Const 13)],
                match(Const 13, Variable "my_var")
            ),
            assertEquals("empty binding list for matching UnitP", SOME [], match(Unit, UnitP)),
            assertEquals("empty binding list for matching ConstP", SOME [], match(Const 17, ConstP 17)),
            assertEquals("binding list for matching ConstructorP", SOME [("my_var", Const 13)],
                match(Constructor("my_constructor", Const 13), ConstructorP("my_constructor", Variable "my_var"))
            ),
            assertEquals("binding list for matching TupleP", SOME [("my_var", Const 13), ("other_var", Const 17)],
                match(Tuple [Const 13, Const 17], TupleP [Variable "my_var", Variable "other_var"])
            )
        ]),
        ("first_match", [
            assertEquals("empty binding list for Wildcard pattern", SOME [],
                first_match (Const 16) [UnitP, Wildcard, Variable "my_var"]
            ),
            assertEquals("one binding for Variable pattern", SOME [("my_var", Const 16)],
                first_match (Const 16) [UnitP, Variable "my_var", Wildcard]
            ),
            assertNone("for no matching pattern",
                first_match (Const 16) [UnitP, ConstP 32, ConstructorP ("my_constructor", Variable "my_var")]
            )
        ]),
        ("typecheck_patterns", [
            assertEquals("Anything-TupleT for first hw-example",
                SOME (TupleT [Anything, Anything]),
                typecheck_patterns([], [TupleP [Variable "x", Variable "y"], TupleP [Wildcard, Wildcard]])),
            assertEquals("nested Anything-TupleT for second hw-example",
                SOME (TupleT [Anything, TupleT [Anything, Anything]]),
                typecheck_patterns([], [TupleP [Wildcard, TupleP [Wildcard, Wildcard]], TupleP [Wildcard, Wildcard]])),
            assertNone("for exception UnmatchedConstructor",
                typecheck_patterns([], [
                    TupleP [Wildcard, TupleP [Wildcard, Wildcard]],
                    TupleP [Wildcard, Wildcard],
                    TupleP [ConstructorP("my_cons", Variable "my_var"), Wildcard]
                ])),
            assertEquals("TupleT with Datatype for example with valid Constructor",
                SOME (TupleT [Datatype "c_my_type", TupleT [Anything, Anything]]),
                typecheck_patterns([("my_cons", "c_my_type", IntT)], [
                    TupleP [Wildcard, TupleP [Wildcard, Wildcard]],
                    TupleP [Wildcard, Wildcard],
                    TupleP [ConstructorP("my_cons", ConstP 13), Wildcard]
                ]))
        ])
    ]
    val _ = print "\n\n";
in
    case onlyFailedModules tests of
        [] => print("SUCCESS\n\n")
        | results => printResults(results)
end

Batch Geonews: Voxel.js Minecraft-like, QGIS for Android, Side-by-Side Router, and much more

$
0
0

Here’s the recent geonews in batch mode.

On the open source front:

On the Esri front:

On the Google front:

In the miscellaneous category:

In the maps category:



用于展现图表的50种JavaScript库

$
0
0

在很多项目中都会有在前端展现数据图表的需求,而在开发过程中,开发者往往会使用一些JavaScript库,从而更有效地达到想要的目标。最近,TechSlide上的一篇文章总结了50种用于展现图表的JavaScript库,并对每种库做了简要的说明。这对于想要选择合适JavaScript库的开发者很有参考意义。

文章作者首推的库是D3,他说到:

  它非常让人惊叹,我很喜欢它的简洁性。它的文档非常完备,源代码托管在GitHub上,而且不断会添加新的示例。有一种叫做Tributary的创建D3原型的工具,其中有很多非常棒的示例。这个库非常好,以至于xcharts、nvd3、Rickshaw、Cubism.js、dc.js、xkcd都是基于它构建的。如果你想要做出优秀的自定义数据可视化效果,那么D3可能是你最佳选择,或者对于更简单的图,你可以选择上面所提到的基于D3的库。最后,我强烈推荐阅读Scott Murray关于D3的免费书《Interactive Data Visualization for the Web》和《Dashing D3 tutorials》。

接下来,他列举并简要说明了其它用于展现数据、制作表格和图表的JavaScript库,列在前20位的如下:

  • HighCharts——它非常强大,你可以在JSFiddle中查看和编辑大量示例。它不免费,但拥有很多客户(IBM、NASA、MasterCard等)。它还向下兼容IE 8。
  • jqPlot——如果你已经在使用jQuery,不想为HighCharts付费,而且情况很简单,不需要D3那样复杂的库,那么jqPlot是很好的选择。
  • dygraphs——一种开源的JavaScript库,可以做出可交互、可缩放的时间线图表。对于大数据集合非常适用。
  • Protovis——和D3出自同一支团队之手,是一种免费的开源库。你可以查看这个stackoveflow 页面来了解D3与其的区别。
  • Flot Charts——与jqPlot一样,Flot是一种针对jQuery的纯JavaScript库,专注于简单的用法、引人注目的外观和交互特性。
  • Google Chart Tools——强大、免费、易于使用。内容丰富,从最简单的线状图到负责的层级树状图都有,在展示页面中提供了大量设计良好的图表类型。
  • dc.js——基于D3的JavaScript图表库,拥有本地跨过滤器(crossfilter)的支持,并让你可以高效率地浏览大型多维数据集。
  • xcharts——基于D3用于构建自定义图表的库。
  • nvd3——让你可以构建可重用的图表和图表组件,同时具有d3.js的强大功能。
  • rickshaw——用于创建可交互时间线图表的JavaScript工具。
  • Cubism.js——用于可视化时间线的D3插件。使用了Cubism构建更好的实时仪表盘,可以从Graphite、Cube和其他源拉取数据。
  • xkcd——让你可以使用D3在JavaScript中做出XKCD样式的图表。
  • jQuery Sparklines——一种jQuery插件,可以直接在浏览器中创建小型的内嵌图表。
  • peity——一种简单的jQuery插件,可以把元素的内容转换成简单的饼图、线图和柱状图。
  • BonsaiJS——一种轻量级的图形库,拥有直观的图形API和SVG渲染器。
  • Flotr——为Prototype.js所用的JavaScript图表库。它拥有很多特性,像对负数值的支持、鼠标跟踪、选定支持、缩放支持、事件挂钩、CSS样式支持、在画布(canvas)中包含文字、旋转的标签、渐变颜色、图形标题和子标题、电子表格、CSV数据下载等等。
  • ProtoChart——物如其名,ProtoChart让你可以使用JavaScript和Prototype创建很漂亮的图表。它是一种开源库。
  • Flotr2——HumbleSoftware当前正在做的项目,让你可以使用Canvas和JavaScript创建图表。
  • jQuery-Visualize——HTML的table元素驱动的HTML5 canvas图表。也是针对jQuery的图表插件。
  • JS Charts——基于JavaScript的图表生成器,只需要很少甚至不需要编码。免费版会有水印,可以通过付费去掉。
  • ……

文章中还列举的JavaScript库有:PlotKitMilkChartmoochartmoowheeltable2chartCanvas 3D GraphTufteGraphArborJSTimePlotgRaphaelICOElychartsZingChartRGraphDojo ChartingBluffcanvasXpressccchartJITJSXGraphSmoothie ChartsYUI ChartsamchartsEmprise JavaScript ChartsFusionChartsJavaScript Diagram BuilderjGraphSencha Touch ChartsStyle ChartAwesomeChartJS等,都各有千秋,如果你对这些库感兴趣的话,可以访问相应的链接或者阅读原文

这个列表对于想要利用JavaScript技术创建图表展现数据的开发者来说,非常具有参考意义,你可以从中选择最适合的库,从而高效、高质量地完成任务。

50 JAVASCRIPT LIBRARIES FOR CHARTS AND GRAPHS

How are you visualizing data in JavaScript? What is your favorite library for creating charts and graphs with JavaScript?

I have been a long time fan of jqPlot for its open source approach, simplicity, examples, and great features. It performs well, it is used by many corporations, and it is built on top of jQuery. Recently, however, D3 has really caught my eye. It uses JavaScript, HTML, SVG and CSS to really bring data to life. It is also open sourced, does not depend on jQuery, has a ton of examples, and there are even some good charting libraries based on D3. The other big player isHighCharts, also written in pure JavaScript with all demos that you can view and edit in JSFiddleand it also has some powerful features. Beyond these three, there are many more useful JavaScript charting libraries worth considering. Here is a list of the top 50 JS libraries for making charts and graphs:

D3 – is really amazing and I love it’s simplicity. The documentation is really extensive, the source code is hosted on GitHub, and the examples are never-ending. There is a D3 prototyping tool called Tributary with many great examples. It’s so good that xcharts, nvd3, Rickshaw, Cubism.js, dc.js, and xkcd are all based on D3. If you are making some amazing custom data visualizations, D3 should probably be your choice, otherwise these d3-based libraries mentioned above are great for more simple straightforward graphs. Finally, I highly recommend looking at Scott Murray free book on D3 called Interactive Data Visualization for the Web and Dashing D3 tutorials.

HighCharts – very powerful, I love the JSFiddle examples and powerful features. I don’t like the license fee but they have great customers (IBM, NASA, MasterCard, etc). They also have backward compatibility with IE8.

jqPlot – if you are already using jQuery, you don’t want to pay for HighCharts, and D3 is too much for your simple use cases, then jqPlot is an excellent choice.

dygraphs – open source JavaScript library that produces interactive, zoomable charts of time series. It is really excellent for large data sets.

Protovis – free and open-source created by the same team that is now working on D3. If you are interested in comparing D3 to Protovis, check out this stackoveflow page.

Flot Charts – similar to jqPlot, Flot is a pure JavaScript plotting library for jQuery, with a focus on simple usage, attractive looks and interactive features. If you are interested in comparing Flot to jqPlot, this thread has some good information.

Google Chart Tools – powerful, free, simple to use, and it has everything from simple line charts to complex hierarchical tree maps, the chart galley provides a large number of well-designed chart types.

dc.js – a javascript charting library based on D3 with native crossfilter support and allowing highly efficient exploration on large multi-dimensional dataset.

xcharts – a D3-based library for building custom charts and graphs.

nvd3 – allows you to build re-usable charts and chart components without taking away the power that d3.js gives you.

rickshaw – JavaScript toolkit for creating interactive time series graphs.

Cubism.js – a D3 plugin for visualizing time series. Use Cubism to construct better realtime dashboards, pulling data from Graphite, Cube and other sources.

xkcd – allows you to make XKCD-style plots in Javascript using D3. Check out xkcdgraphs to make your own xkcd graphs.

jQuery Sparklines – a jQuery plugin that creates small inline charts directly in the browser.

peity – a simple jQuery plugin that converts an element’s content into a simple CANVAS mini pie, line or bar chart.

BonsaiJS – lightweight graphics library with an intuitive graphics API and an SVG renderer.

Flotr – a Javascript plotting library for Prototype.js. It comes with great features like legend support, negative value support, mouse tracking, selection support, zoom support, event hooks, css styling support, text included into the canvas, rotated labels, color gradients, graph title and subtitle, spreadsheet, CSV data download and much more.

ProtoChart – As the name suggests, ProtoChart allows you to create beautiful charts using Javascript and Prototype. It is open sourced, uses Canvas, and was highly motivated by Flot, Flotr and PlotKit libraries.

Flotr2 – a recent project by HumbleSoftware that lets you make graphs and charts with Canvas and JavaScript. HumbleSoftware also came out with envisionjs which uses flotr2 and allows you to make dynamic HTML5 visualizations.

jQuery-Visualize – HTML5 canvas charts driven by HTML table elements. Another charting plugin for jQuery.

JS Charts – a JavaScript based chart generator that requires little or no coding. The free version has a watermark which can be removed by paying for a license.

PlotKit – a chart and graph plotting Library for Javascript. It has support for HTML Canvas and also SVG via Adobe SVG Viewer and native browser support. PlotKit is a complete rewrite ofCanvasGraph.

MilkChart – a compact JavaScript framework for creating graphs based on MooTools. It is simple and easy to understand.

moochart – is another plugin for MooTools and it focuses on drawing bubble diagrams on the canvas tag.

moowheel – a JavaScript connections visualization library based on MooTools.

table2chart – a MooTools plugin that generates charts from accessible data tables.

Canvas 3D Graph – a special type of bar graph that plot numbers in 3D.

TufteGraph – another JavaScript charting library based on jQuery. It has a really compact API and non-core layout is done via CSS.

ArborJS – a graph visualization library using web workers and jQuery.

TimePlot – focused entirely on graphing time-series data, with support for annotating the graph with temporal events.

gRaphael – create stunning charts on your website, based on Raphael graphics library.

ICO – another JavaScript graph library based on Raphael.

Elycharts – a pure javascript charting library, easy to use and completely customizable. It is based on jQuery and Raphaël libraries.

ZingChart – allows you to build advanced charts and visualizations in HTML5, SVG, VML and Flash.

RGraph – produces interactive charts using the HTML5 canvas tag.

Dojo Charting – if you are already using Dojo, then Dojo’s charting library is a great solution for making charts and graphs.

Bluff – Bluff is a JavaScript port of the Gruff graphing library for Ruby. It is designed to support all the features of Gruff with minimal dependencies.

canvasXpress – a javascript library based on the Canvas tag implemented in HTML5.

ccchart – a Simple JavaScript chart that does not depend on libraries such as jQuery.

JIT – JavaScript InfoVis Toolkit provides tools for creating Interactive Data Visualizations for the Web.

JSXGraph – a cross-browser library for interactive geometry, function plotting, charting, and data visualization in a web browser.

Smoothie Charts – a JavaScript Charting Library for Streaming Data.

YUI Charts – YUI module that provides a JavaScript API for visualizing data in a variety of formats leveraging SVG, HTML Canvas and VML to render its graphical elements.

amcharts – JavaScript/HTML5 charts including serial (column, bar, line, area, step line, smoothed line, candlestick and ohlc graphs), pie/donut, radar/polar and xy/scatter/bubble charts.

Emprise JavaScript Charts – pure JavaScript charts with great features and good cross browser support.

FusionCharts – delightful data visualization for your needs, a chart web service powering more than a billion charts per month.

JavaScript Diagram Builder – a library of some objects and functions, which can help you to display a chart or graph in an easy way.

jGraph – HTML5 diagramming component with full IE 6-8 and touch device support.

Sencha Touch Charts – it uses HTML5 Canvas and CSS3 to deliver charts to the mobile web browsers.

Style Chart – a free Ajax Visualization Charting Service

If you are looking for more libraries and web services that deal with visualizing data, I recommend checking out Datavisualization.ch.

Have I missed any good JavaScript charting libraries?

Update:

AwesomeChartJS – great looking charts with JavaScript and the canvas element
Sigma.js – an open-source lightweight JavaScript library to make network visualizations using the HTML canvas element.

 


Programming Languages Programming Assignment 4

$
0
0
#lang racket
(define ones (lambda () (cons 1 ones)))
(define nats
  (letrec ([f (lambda (x) (cons x (lambda () (f (+ x 1)))))])
    (lambda () (f 1))))
(define powers-of-two
  (letrec ([f (lambda (x) (cons x (lambda () (f (* x 2)))))])
    (lambda () (f 2))))

(define (sequence low high stride)
  (if (> low high)
      null
      (cons low (sequence (+ low stride) high stride))))

(define (string-append-map xs suffix)
  (map (lambda (str) (string-append str suffix))
       xs))

(define (list-nth-mod xs n)
  (cond [(< n 0) (error "list-nth-mod: negative number")]
        [(null? xs) (error "list-nth-mod: empty list")]
        [#t (let 
              ([i (remainder n (length xs))]) 
              (car (list-tail xs i))
             )]))

(define (stream-for-n-steps s n)
  (if (= n 0)
      null 
      (cons (car (s)) (stream-for-n-steps (cdr (s)) (- n 1))))
  )

(define (stream-maker fn arg)
  (letrec ([f (lambda (x)
                (cons x (lambda () (f (fn x arg)))))])
     (lambda () (f arg))))

(define funny-number-stream (stream-maker (lambda (x y) (cond [(= (remainder x 5) 4) (- (+ x 1))]
                                                              [(= (remainder x 5) 0) (- (- x 1))]
                                                              [#t (+ x 1)])) 1))

(define dan-then-dog (stream-maker (lambda (x y) (cond [(equal? x "dan.jpg") "dog.jpg"]
                                                       [#t "dan.jpg"])) "dan.jpg"))	

(define (stream-add-zero s)
   (lambda () (cons (cons 0 (car (s))) (stream-add-zero (cdr (s))))))

(define (cycle-lists xs ys)
   (letrec ([f (lambda (n)
                (cons (cons (list-ref xs (remainder n (length xs))) 
                            (list-ref ys (remainder n (length ys)))) 
                      (lambda () (f (+ n 1)))))])
     (lambda () (f 0))))

(define (vector-assoc v vec)
     (letrec ([f (lambda (n)
                (cond [(= n (vector-length vec)) #f]
                      [(pair? (vector-ref vec n)) (if (equal? v (car (vector-ref vec n))) (vector-ref vec n) (f (+ n 1)))] 
                      [#t (f (+ n 1))]))])
     (f 0))
  )

(define (cached-assoc xs n)
  (letrec([memo (make-vector n #f)]
          [curIdx 0]
          [f (lambda (x)
             (let ([ans (vector-assoc x memo)])
               (if ans
                 ans
                 (let ([new-ans (assoc x xs)])
                   (if new-ans 
                       (begin (vector-set! memo curIdx new-ans) 
                                      (set! curIdx (remainder (+ curIdx 1) n)) 
                                      new-ans) 
                       #f)
                   ))))])
  f))

Programming Languages Programming Assignment 5

$
0
0
;; Programming Languages, Homework 5

#lang racket
(provide (all-defined-out)) ;; so we can put tests in a second file

;; definition of structures for MUPL programs - Do NOT change
(struct var  (string) #:transparent)  ;; a variable, e.g., (var "foo")
(struct int  (num)    #:transparent)  ;; a constant number, e.g., (int 17)
(struct add  (e1 e2)  #:transparent)  ;; add two expressions
(struct ifgreater (e1 e2 e3 e4)    #:transparent) ;; if e1 > e2 then e3 else e4
(struct fun  (nameopt formal body) #:transparent) ;; a recursive(?) 1-argument function
(struct call (funexp actual)       #:transparent) ;; function call
(struct mlet (var e body) #:transparent) ;; a local binding (let var = e in body) 
(struct apair (e1 e2)     #:transparent) ;; make a new pair
(struct fst  (e)    #:transparent) ;; get first part of a pair
(struct snd  (e)    #:transparent) ;; get second part of a pair
(struct aunit ()    #:transparent) ;; unit value -- good for ending a list
(struct isaunit (e) #:transparent) ;; evaluate to 1 if e is unit else 0

;; a closure is not in "source" programs; it is what functions evaluate to
(struct closure (env fun) #:transparent) 

;; Problem 1
(define (racketlist->mupllist xs)
   (if (null? xs)
       (aunit)
       (apair (car xs) (racketlist->mupllist (cdr xs)))
       )
  )
(define (mupllist->racketlist ms)
   (if (aunit? ms)
       null
       (cons (apair-e1 ms) (mupllist->racketlist (apair-e2 ms)))
       )
  )
;; CHANGE (put your solutions here)

;; Problem 2

;; lookup a variable in an environment
;; Do NOT change this function
(define (envlookup env str)
  (cond [(null? env) (error "unbound variable during evaluation" str)]
        [(equal? (car (car env)) str) (cdr (car env))]
        [#t (envlookup (cdr env) str)]))

;; Do NOT change the two cases given to you.  
;; DO add more cases for other kinds of MUPL expressions.
;; We will test eval-under-env by calling it directly even though
;; "in real life" it would be a helper function of eval-exp.
(define (eval-under-env e env)
  (cond [(var? e) 
         (envlookup env (var-string e))]
        [(add? e) 
         (let ([v1 (eval-under-env (add-e1 e) env)]
               [v2 (eval-under-env (add-e2 e) env)])
           (if (and (int? v1)
                    (int? v2))
               (int (+ (int-num v1) 
                       (int-num v2)))
               (error "MUPL addition applied to non-number")))]
        ;; CHANGE add more cases here
        [(int? e) e]
        [(fun? e) (closure env e)]        
        [(ifgreater? e) 
         (let ([v1 (eval-under-env (ifgreater-e1 e) env)]
               [v2 (eval-under-env (ifgreater-e2 e) env)])
           (if (and (int? v1)
                    (int? v2))
               (if (> (int-num v1) (int-num v2))
                   (eval-under-env (ifgreater-e3 e) env)
                   (eval-under-env (ifgreater-e4 e) env))
           (error "MUPL ifgreater applied to non-number")))]
        [(call? e) 
         (let ([callClosure (eval-under-env (call-funexp e) env)]
               [callEnv (eval-under-env (call-actual e) env)])
           (if (closure? callClosure) 
               (let* ([callClosureFun (closure-fun callClosure)]
                      [callClosureEnv (closure-env callClosure)]
                      [cn (cons (fun-nameopt callClosureFun) callClosure)]
                      [cf (cons (fun-formal callClosureFun) callEnv)]) 
                 (eval-under-env 
                  (fun-body callClosureFun)
                  (if (eq? (car cn) #f) 
                      (cons cf callClosureEnv) 
                      (cons cf (cons cn callClosureEnv))))) 
               (error "MUPL call applied to non-closure")))]
        [(mlet? e) 
            (let ([v (eval-under-env (mlet-e e) env)])
                (eval-under-env (mlet-body e) (cons (cons (mlet-var e) v) env)))]
        [(apair? e) (apair (eval-under-env (apair-e1 e) env)
                           (eval-under-env (apair-e2 e) env))]
        [(fst? e) (let ([v (eval-under-env (fst-e e) env)]) 
                    (if (apair? v) 
                        (apair-e1 v) 
                        (error "MUPL fst applied to non-pair")))]
        [(snd? e) (let ([v (eval-under-env (snd-e e) env)]) 
                    (if (apair? v) 
                        (apair-e2 v) 
                        (error "MUPL snd applied to non-pair")))]
        [(aunit? e) e]
        [(isaunit? e) 
            (if (aunit? (eval-under-env (isaunit-e e) env)) 
                (int 1) 
                (int 0))]
        [(closure? e) e]
        [#t (error "bad MUPL expression")]))

;; Do NOT change
(define (eval-exp e)
  (eval-under-env e null))
        
;; Problem 3

(define (ifaunit e1 e2 e3) 
  (ifgreater (isaunit e1) (int 0) e2 e3))

(define (mlet* lstlst e2) 
  (if (null? lstlst) 
      e2 
      (mlet 
        (car (car lstlst))
        (cdr (car lstlst))
        (mlet* (cdr lstlst) e2)
        )))

(define (ifeq e1 e2 e3 e4) 
  (mlet* (list (cons "_x" e1) (cons "_y" e2)) 
         (ifgreater (var "_x") (var "_y") e4
                    (ifgreater (var "_y") (var "_x") e4 e3))))

;; Problem 4

(define mupl-map 
  (fun #f "f1" 
       (fun "recursive" "list" 
            (ifgreater 
                (isaunit (var "list")) 
                (int 0)
                (aunit)
                (apair
                   (call (var "f1") (fst (var "list")))
                   (call (var "recursive") (snd (var "list"))))))))

(define mupl-mapAddN 
  (mlet "map" mupl-map
        (fun #f "i"
             (call (var "map") 
                   (fun #f "j" 
                        (add (var "i") (var "j")))))))

;; Challenge Problem

(struct fun-challenge (nameopt formal body freevars) #:transparent) ;; a recursive(?) 1-argument function

;; We will test this function directly, so it must do
;; as described in the assignment
(define (compute-free-vars e) "CHANGE")

;; Do NOT share code with eval-under-env because that will make
;; auto-grading and peer assessment more difficult, so
;; copy most of your interpreter here and make minor changes
(define (eval-under-env-c e env) "CHANGE")

;; Do NOT change this
(define (eval-exp-c e)
  (eval-under-env-c (compute-free-vars e) null))


Programming Languages Programming Assignment 6

$
0
0
# University of Washington, Programming Languages, Homework 6, hw6runner.rb

# This is the only file you turn in, so do not modify the other files as
# part of your solution.

class MyTetris < Tetris
  # your enhancements here
  def initialize
	super
	@root.bind('u', proc {@board.rotate_180degrees})
	@root.bind('c', proc {@board.enter_cheat})	
  end

  def set_board
    @canvas = TetrisCanvas.new
    @board = MyBoard.new(self)
    @canvas.place(@board.block_size * @board.num_rows + 3,
                  @board.block_size * @board.num_columns + 6, 24, 80)
    @board.draw
  end  
end

class MyPiece < Piece
  # The constant All_My_Pieces should be declared here
    All_My_Pieces =  Piece::All_Pieces + [rotations([[0, 0], [0, -1], [1, 0], [1, -1], [2, -1]]),
			      [[[0, 0], [-1, 0], [1, 0], [2, 0], [3, 0]], # long (only needs two)
                  [[0, 0], [0, -1], [0, 1], [0, 2], [0, 3]]],
				  rotations([[0, 0], [0, -1], [1, -1]])]
  # your enhancements here
  def self.next_piece (board)
    MyPiece.new(All_My_Pieces.sample, board)
  end
  def self.cheat_piece (board)
    MyPiece.new([[[0, 0]]], board)
  end  
end

class MyBoard < Board
  # your enhancements here
  def initialize (game)
    @grid = Array.new(num_rows) {Array.new(num_columns)}
    @current_block = MyPiece.next_piece(self)
    @score = 0
    @game = game
    @delay = 500
  end
  # gets the next piece
  def next_piece
    if @cheat 
	  @current_block = MyPiece.cheat_piece(self)
	  @cheat = false
	else
      @current_block = MyPiece.next_piece(self)
	end
    @current_pos = nil	
  end
  def store_current
    locations = @current_block.current_rotation
    displacement = @current_block.position
    (0..(locations.length-1)).each{|index| 
      current = locations[index];
      @grid[current[1]+displacement[1]][current[0]+displacement[0]] = 
      @current_pos[index]
    }
    remove_filled
    @delay = [@delay - 2, 80].max
  end  
  def rotate_180degrees
    if !game_over? and @game.is_running?
      @current_block.move(0, 0, 2)
    end
    draw
  end
  def enter_cheat
	if !@cheat and @score >= 100
       @score = @score - 100
	   @cheat = true
    end
  end
end

# University of Washington, Programming Languages, Homework 6, hw6provided.rb

require_relative './hw6graphics'

# class responsible for the pieces and their movements
class Piece 
  
  # creates a new Piece from the given point array, holding the board for 
  # determining if movement is possible for the piece, and gives the piece a 
  # color, rotation, and starting position.
  def initialize (point_array, board)
    @all_rotations = point_array
    @rotation_index = (0..(@all_rotations.size-1)).to_a.sample
    @color = All_Colors.sample
    @base_position = [5, 0] # [column, row]
    @board = board
    @moved = true
  end

  def current_rotation
    @all_rotations[@rotation_index]
  end
  
  def moved
    @moved
  end

  def position
    @base_position
  end

  def color
    @color
  end

  def drop_by_one
    @moved = move(0, 1, 0)
  end

  # takes the intended movement in x, y and rotation and checks to see if the
  # movement is possible.  If it is, makes this movement and returns true. 
  # Otherwise returns false.
  def move (delta_x, delta_y, delta_rotation)
    # Ensures that the rotation will always be a possible formation (as opposed 
    # to nil) by altering the intended rotation so that it stays 
    # within the bounds of the rotation array
    moved = true
    potential = @all_rotations[(@rotation_index + delta_rotation) % @all_rotations.size]
    # for each individual block in the piece, checks if the intended move
    # will put this block in an occupied space
    potential.each{|posns| 
      if !(@board.empty_at([posns[0] + delta_x + @base_position[0],
                            posns[1] + delta_y + @base_position[1]]));
        moved = false;  
      end
    }
    if moved
      @base_position[0] += delta_x
      @base_position[1] += delta_y
      @rotation_index = (@rotation_index + delta_rotation) % @all_rotations.size
    end
    moved
  end

  # class method to figures out the different rotations of the provided piece
  def self.rotations (point_array)
    rotate1 = point_array.map {|x,y| [-y,x]}  
    rotate2 = point_array.map {|x,y| [-x,-y]} 
    rotate3 = point_array.map {|x,y| [y,-x]}  
    [point_array, rotate1, rotate2, rotate3]  
  end

  # class method to choose the next piece
  def self.next_piece (board)
    Piece.new(All_Pieces.sample, board)
  end
  
  # class array holding all the pieces and their rotations
  All_Pieces = [[[[0, 0], [1, 0], [0, 1], [1, 1]]],  # square (only needs one)
               rotations([[0, 0], [-1, 0], [1, 0], [0, -1]]), # T
               [[[0, 0], [-1, 0], [1, 0], [2, 0]], # long (only needs two)
               [[0, 0], [0, -1], [0, 1], [0, 2]]],
               rotations([[0, 0], [0, -1], [0, 1], [1, 1]]), # L
               rotations([[0, 0], [0, -1], [0, 1], [-1, 1]]), # inverted L
               rotations([[0, 0], [-1, 0], [0, -1], [1, -1]]), # S
               rotations([[0, 0], [1, 0], [0, -1], [-1, -1]])] # Z

  # class array 
  All_Colors = ['DarkGreen', 'dark blue', 'dark red', 'gold2', 'Purple3', 
               'OrangeRed2', 'LightSkyBlue']  
end


# Class responsible for the interaction between the pieces and the game itself
class Board

  def initialize (game)
    @grid = Array.new(num_rows) {Array.new(num_columns)}
    @current_block = Piece.next_piece(self)
    @score = 0
    @game = game
    @delay = 500
  end
   
  # both the length and the width of a block, since it is a square
  def block_size
    15
  end
  
  def num_columns
    10
  end

  def num_rows
    27
  end
  
  # the current score
  def score
    @score
  end

  # the current delay
  def delay
    @delay
  end

  # the game is over when there is a piece extending into the second row 
  # from the top
  def game_over?
    @grid[1].any?
  end

  # moves the current piece down by one, if this is not possible stores the
  # current piece and replaces it with a new one.
  def run
    ran = @current_block.drop_by_one
    if !ran
      store_current
      if !game_over?
        next_piece
      end
    end
    @game.update_score
    draw
  end

  # moves the current piece left if possible
  def move_left
    if !game_over? and @game.is_running?
      @current_block.move(-1, 0, 0)
    end
    draw
  end

  # moves the current piece right if possible
  def move_right
    if !game_over? and @game.is_running?
      @current_block.move(1, 0, 0)
    end
    draw
  end

  # rotates the current piece clockwise
  def rotate_clockwise
    if !game_over? and @game.is_running?
      @current_block.move(0, 0, 1)
    end
    draw
  end

  # rotates the current piece counterclockwise
  def rotate_counter_clockwise
    if !game_over? and @game.is_running?
      @current_block.move(0, 0, -1)
    end
    draw
  end
  
  # drops the piece to the lowest location in the currently occupied columns.
  # Then replaces it with a new piece
  # Change the score to reflect the distance dropped.
  def drop_all_the_way
    if @game.is_running?
      ran = @current_block.drop_by_one
      while ran
        @current_pos.each{|block| block.remove}
        @score += 1
        ran = @current_block.drop_by_one
      end
      draw
      store_current
      if !game_over?
        next_piece
      end
      @game.update_score
      draw
    end
  end

  # gets the next piece
  def next_piece
    @current_block = Piece.next_piece(self)
    @current_pos = nil
  end

  # gets the information from the current piece about where it is and uses this
  # to store the piece on the board itself.  Then calls remove_filled.
  def store_current
    locations = @current_block.current_rotation
    displacement = @current_block.position
    (0..3).each{|index| 
      current = locations[index];
      @grid[current[1]+displacement[1]][current[0]+displacement[0]] = 
      @current_pos[index]
    }
    remove_filled
    @delay = [@delay - 2, 80].max
  end

  # Takes a point and checks to see if it is in the bounds of the board and 
  # currently empty.
  def empty_at (point)
    if !(point[0] >= 0 and point[0] < num_columns)
      return false
    elsif point[1] < 1
      return true
    elsif point[1] >= num_rows
      return false
    end
    @grid[point[1]][point[0]] == nil
  end

  # removes all filled rows and replaces them with empty ones, dropping all rows
  # above them down each time a row is removed and increasing the score.  
  def remove_filled
    (2..(@grid.size-1)).each{|num| row = @grid.slice(num);
      # see if this row is full (has no nil)
      if @grid[num].all?
        # remove from canvas blocks in full row
        (0..(num_columns-1)).each{|index|
          @grid[num][index].remove;
          @grid[num][index] = nil
        }
        # move down all rows above and move their blocks on the canvas
        ((@grid.size - num + 1)..(@grid.size)).each{|num2|
          @grid[@grid.size - num2].each{|rect| rect && rect.move(0, block_size)};
          @grid[@grid.size-num2+1] = Array.new(@grid[@grid.size - num2])
        }
        # insert new blank row at top
        @grid[0] = Array.new(num_columns);
        # adjust score for full flow
        @score += 10;
      end}
    self
  end

  # current_pos holds the intermediate blocks of a piece before they are placed 
  # in the grid.  If there were any before, they are sent to the piece drawing 
  # method to be removed and replaced with that of the new position
  def draw
    @current_pos = @game.draw_piece(@current_block, @current_pos)
  end
end

class Tetris

  # creates the window and starts the game
  def initialize
    @root = TetrisRoot.new
    @timer = TetrisTimer.new
    set_board
    @running = true
    key_bindings
    buttons
    run_game
  end

  # creates a canvas and the board that interacts with it
  def set_board
    @canvas = TetrisCanvas.new
    @board = Board.new(self)
    @canvas.place(@board.block_size * @board.num_rows + 3,
                  @board.block_size * @board.num_columns + 6, 24, 80)
    @board.draw
  end

  def key_bindings  
    @root.bind('n', proc {self.new_game}) 

    @root.bind('p', proc {self.pause}) 

    @root.bind('q', proc {exitProgram})
    
    @root.bind('a', proc {@board.move_left})
    @root.bind('Left', proc {@board.move_left}) 
    
    @root.bind('d', proc {@board.move_right})
    @root.bind('Right', proc {@board.move_right}) 

    @root.bind('s', proc {@board.rotate_clockwise})
    @root.bind('Down', proc {@board.rotate_clockwise})

    @root.bind('w', proc {@board.rotate_counter_clockwise})
    @root.bind('Up', proc {@board.rotate_counter_clockwise}) 
    
    @root.bind('space' , proc {@board.drop_all_the_way}) 
  end

  def buttons
    pause = TetrisButton.new('pause', 'lightcoral'){self.pause}
    pause.place(35, 50, 90, 7)

    new_game = TetrisButton.new('new game', 'lightcoral'){self.new_game}
    new_game.place(35, 75, 15, 7)
    
    quit = TetrisButton.new('quit', 'lightcoral'){exitProgram}
    quit.place(35, 50, 140, 7)
    
    move_left = TetrisButton.new('left', 'lightgreen'){@board.move_left}
    move_left.place(35, 50, 27, 536)
    
    move_right = TetrisButton.new('right', 'lightgreen'){@board.move_right}
    move_right.place(35, 50, 127, 536)
    
    rotate_clock = TetrisButton.new('^_)', 'lightgreen'){@board.rotate_clockwise}
    rotate_clock.place(35, 50, 77, 501)

    rotate_counter = TetrisButton.new('(_^', 'lightgreen'){
      @board.rotate_counter_clockwise}
    rotate_counter.place(35, 50, 77, 571)
    
    drop = TetrisButton.new('drop', 'lightgreen'){@board.drop_all_the_way}
    drop.place(35, 50, 77, 536)

    label = TetrisLabel.new(@root) do
      text 'Current Score: '   
      background 'lightblue'
    end
    label.place(35, 100, 26, 45)
    @score = TetrisLabel.new(@root) do
      background 'lightblue'
    end
    @score.text(@board.score)
    @score.place(35, 50, 126, 45)    
  end

  # starts the game over, replacing the old board and score
  def new_game
    @canvas.unplace
    @canvas.delete
    set_board
    @score.text(@board.score)
    @running = true
    run_game
  end

  # pauses the game or resumes it
  def pause
    if @running
      @running = false
      @timer.stop
    else
      @running = true
      self.run_game
    end
  end

  # alters the displayed score to reflect what is currently stored in the board
  def update_score
    @score.text(@board.score)
  end

  # repeatedly calls itself so that the process is fully automated.  Checks if
  # the game is over and if it isn't, calls the board's run method which moves
  # a piece down and replaces it with a new one when the old one can't move any
  # more
  def run_game
    if !@board.game_over? and @running
      @timer.stop
      @timer.start(@board.delay, (proc{@board.run; run_game}))
    end
  end

  # whether the game is running
  def is_running?
    @running
  end

  # takes a piece and optionally the list of old TetrisRects corresponding
  # to it and returns a new set of TetrisRects which are how the piece is 
  # visible to the user.
  def draw_piece (piece, old=nil)
    if old != nil and piece.moved
      old.each{|block| block.remove}
    end
    size = @board.block_size
    blocks = piece.current_rotation
    start = piece.position
    blocks.map{|block| 
    TetrisRect.new(@canvas, start[0]*size + block[0]*size + 3, 
                       start[1]*size + block[1]*size,
                       start[0]*size + size + block[0]*size + 3, 
                       start[1]*size + size + block[1]*size, 
                       piece.color)}
  end
end

# To help each game of Tetris be unique.
srand

# University of Washington, Programming Languages, Homework 6, hw6runner.rb

require_relative './hw6provided'
require_relative './hw6assignment'

def runTetris
  Tetris.new 
  mainLoop
end

def runMyTetris
  MyTetris.new
  mainLoop
end

if ARGV.count == 0
  runMyTetris
elsif ARGV.count != 1
  puts "usage: hw6runner.rb [enhanced | original]"
elsif ARGV[0] == "enhanced"
  runMyTetris
elsif ARGV[0] == "original"
  runTetris
else
  puts "usage: hw6runner.rb [enhanced | original]"
end


# University of Washington, Programming Languages, Homework 6, hw6graphics.rb

# This file provides an interface to a wrapped Tk library. The auto-grader will
# swap it out to use a different, non-Tk backend.

require 'tk'

class TetrisRoot
  def initialize
    @root = TkRoot.new('height' => 615, 'width' => 205, 
             'background' => 'lightblue') {title "Tetris"}    
  end

  def bind(char, callback)
    @root.bind(char, callback)
  end

  # Necessary so we can unwrap before passing to Tk in some instances.
  # Student code MUST NOT CALL THIS.
  attr_reader :root
end

class TetrisTimer
  def initialize
    @timer = TkTimer.new
  end

  def stop
    @timer.stop
  end

  def start(delay, callback)
    @timer.start(delay, callback)
  end
end

class TetrisCanvas
  def initialize
    @canvas = TkCanvas.new('background' => 'grey')
  end

  def place(height, width, x, y)
    @canvas.place('height' => height, 'width' => width, 'x' => x, 'y' => y)
  end

  def unplace
    @canvas.unplace
  end

  def delete
    @canvas.delete
  end

  # Necessary so we can unwrap before passing to Tk in some instances.
  # Student code MUST NOT CALL THIS.
  attr_reader :canvas
end

class TetrisLabel
  def initialize(wrapped_root, &options)
    unwrapped_root = wrapped_root.root
    @label = TkLabel.new(unwrapped_root, &options)
  end

  def place(height, width, x, y)
    @label.place('height' => height, 'width' => width, 'x' => x, 'y' => y)
  end

  def text(str)
    @label.text(str)
  end
end

class TetrisButton
  def initialize(label, color)
    @button = TkButton.new do 
      text label
      background color
      command (proc {yield})
    end
  end

  def place(height, width, x, y)
    @button.place('height' => height, 'width' => width, 'x' => x, 'y' => y)
  end
end

class TetrisRect
  def initialize(wrapped_canvas, a, b, c, d, color)
    unwrapped_canvas = wrapped_canvas.canvas
    @rect = TkcRectangle.new(unwrapped_canvas, a, b, c, d, 
                             'outline' => 'black', 'fill' => color)
  end

  def remove
    @rect.remove
  end

  def move(dx, dy)
    @rect.move(dx, dy)
  end

end

def mainLoop
  Tk.mainloop
end

def exitProgram
  Tk.exit
end


Pattern-Oriented Software Architectures for Concurrent and Networked Software

$
0
0

1. Concurrent software can simultaneously run multiple computations that potentially interact with each other.

Networked software defines protocols that enable computing devices to exchange messages & perform services remotely.

Motivations for Concurrent software:

1) Leverage hardware/software advances.  multi-core processors and multi-threaded operating systems.

2) Simplify program structure by allowing blocking operations.

3) Increase performance: Parallelize computations and communications.

4) Improve response-time

Challenges for Concurrent software:

1) Accidental Complexities: Tedious, error-prone, non-portable Low-level API. Limited debuging tools

2) Inherent Complexities: Synchronization, Scheduling, Deadlock

Motivations for Networked software:

1) Collaboration & commerce: file sharing, social media, e-commerce.

2) Scalability: cloud computation.

3) Availability: minimizing single points of failure via replication.

4) Cost effectiveness via shared resources.

Challenges for Networked software:

1) Accidental Complexities: Algorithmic decomposition. Continuous re-discovery & re-invention of core components,

2) Inherent Complexities: Latency & jitter, Reliability & partial failure. Security

Describe how patterns & frameworks help address challenges of concurrent & networked software

Patterns:

1)Present solutions to common problems arising within a context.

2) Help balance & resolve key software design forces.

3)  Capture recurring structures & dynamics among software elements to facilitate reuse of successful designs.

4) Codify expert knowledge of design strategies, constraints & “best practices”.

Frameworks: are integrated sets of software components that collaborate to provide reusable architectures for families of related applications.

1)  exhibit “inversion of control” via callback.

2)  provide integrated domain-specific structures & functionality.

3) They are “semi-complete” applications.

Patterns & frameworks codify proven experience to enable

1) Design reuse  - Match problems to relevant structures/dynamics & patterns in a domain.

2) Code reuse – Reify proven designs within particular development environments & domains.

Course Syllabus:

Section 1 – Introduction to concurrent & networked software: Layers, design dimensions, OS programming mechanism, Android programming mechanisms.

Section 2 – Introduction to Patterns & frameworks

Section 3 – Applying patterns & framework to concurrent & networked software. : Event handling, Concurrency, Synchronization.

Week 1.

1. Discuss key layers in concurrent & networked software:

1) Layered architecture create a multi-tier architecture that separates concerns between tasks in different system layers.

Middleware is reusable infrastructure software residing between applications & the underlying operating systems, networks, & hardware.

Middleware leverage hardware & software technology advances, evolve to new requirements & environments, provide an array of reusable, off-the-shelf developer-oriented services. Control end-to-end resources & quality of service (QoS).

Applications

Domain-specific middleware service: are tailed to the requirements of particular domains.

Common Middleware servicees: define higher-level domain-independent services. CORBA component, J2EE, .NET, Webs services.

Distribution Middleware:  simplifies networked component programming & extends OS mechanisms end-to-end. CORBA, SOAP, RMI, DCOM.

Host Infrastructure Middleware: encapsulates/enhances native OS mechanisms to create reusable OO components JVM, CLR

Operating Systems & protocols

Hardware

Pros & Cons of Layers Pattern:

Pros: 1) Reuse of layers, Support for standarization, Dependencies are localized. Exchangeability,

Cons: Cascades of changing behavior, Higher overhead, Unnecessary work, Difficulty of establishing the correct granularity of layers.
2. Explore key design dimensions of concurrent & networked software

Connection-oriented vs. Connectionless Protocols

Data Encoding strategies: Text-based, binary

Connection Multiplexing Strategies: multiplexed connection, nonmultiplexed connection

Sync vs. Async Message Exchange

Message Passing vs. Shared memory

Services, Servers, Configurations

Short vs. Long duration services.

Internal vs. External Services

Monolithic vs. Layered/Modular Services

Single Service vs. Multi-service Servers

One-shot vs. standing Servers

Static vs. Dynamic linking & Configuration.

3. Survey key operating system concurrent & networked software mechanisms & API

Iterative vs. Concurrent Servers.

Multiprocessing vs. Multithreading

Thread/Process Pool Eager Spawning Strategies: Prespawn, On-demand spawning

Kernel- vs. User-level Threading models.  Hybrid threading model.

Task- vs. Message-based Architectures
Describe key Android concurrent & networked software mechanisms & APIs


Ruby function for Option value calculation

$
0
0
class Stock
	def initialize (initial_price = 100, up = 1.04574)
		@initial_price = initial_price
		@up = up
		@down = 1/up
	end
	def calculateStock (n)
		Array.new(n + 1) {|i| @initial_price * (@up**( n - i))*(@down**i)}
	end
	def calculateOption (n, t = 0, strike = 100, r = 1.0005, call = -1)
		q = (r - @down) / (@up - @down)
		q1 = 1- q
		stock_price_n = calculateStock (n)
		option_price_n = stock_price_n.map { |i| [(i - strike)*call, 0].max }
		array_length = n + 1
		(t..(n-1)).each{ |index|
			array_length = array_length - 1
			option_price = calculateStock (array_length - 1).map { |i| [(i - strike)*call, 0].max }
			option_price_n = Array.new(array_length) {|i| 
			    [(option_price_n[i] * q + option_price_n[i+1] * q1)/r, option_price[i]].max 
			}			
		}
		option_price_n
	end	
end

stock = Stock.new
#print stock.calculateStock (0)
#print stock.calculateStock (1)
#print stock.calculateStock (2)
print stock.calculateOption (10)
#print stock.calculateOption (5)
#print stock.calculateOption (6)

Programming Languages Programming Assignment 7

$
0
0

sml code

(* University of Washington, Programming Languages, Homework 7, hw7.sml 
   (See also Ruby code.)
*)

(* Do not make changes to this code except where you see comments containing
   the word CHANGE. *)

(* expressions in a little language for 2D geometry objects
   values: points, lines, vertical lines, line segments
   other expressions: intersection of two expressions, lets, variables, 
                      (shifts added by you)
*)
datatype geom_exp = 
           NoPoints
	 | Point of real * real (* represents point (x,y) *)
	 | Line of real * real (* represents line (slope, intercept) *)
	 | VerticalLine of real (* x value *)
	 | LineSegment of real * real * real * real (* x1,y1 to x2,y2 *)
	 | Intersect of geom_exp * geom_exp (* intersection expression *)
	 | Let of string * geom_exp * geom_exp (* let s = e1 in e2 *)
	 | Var of string
         | Shift of real * real * geom_exp
(* CHANGE add shifts for expressions of the form Shift(deltaX, deltaY, exp *)

exception BadProgram of string
exception Impossible of string

(* helper functions for comparing real numbers since rounding means
   we should never compare for equality *)

val epsilon = 0.00001

fun real_close (r1,r2) = 
    (Real.abs (r1 - r2)) < epsilon

(* notice curried *)
fun real_close_point (x1,y1) (x2,y2) = 
    real_close(x1,x2) andalso real_close(y1,y2)

(* helper function to return the Line or VerticalLine containing 
   points (x1,y1) and (x2,y2). Actually used only when intersecting 
   line segments, but might be generally useful *)
fun two_points_to_line (x1,y1,x2,y2) = 
    if real_close(x1,x2)
    then VerticalLine x1
    else
	let 
	    val m = (y2 - y1) / (x2 - x1)
	    val b = y1 - m * x1
	in
	    Line(m,b)
	end

(* helper function for interpreter: return value that is the intersection
   of the arguments: 25 cases because there are 5 kinds of values, but
   many cases can be combined, especially because intersection is commutative.
   Do *not* call this function with non-values (e.g., shifts or lets)
 *)
fun intersect (v1,v2) =
    case (v1,v2) of
	
       (NoPoints, _) => NoPoints (* 5 cases *)
     | (_, NoPoints) => NoPoints (* 4 additional cases *)

     | 	(Point p1, Point p2) => if real_close_point p1 p2
				then v1
				else NoPoints

      | (Point (x,y), Line (m,b)) => if real_close(y, m * x + b)
				     then v1
				     else NoPoints

      | (Point (x1,_), VerticalLine x2) => if real_close(x1,x2)
					   then v1
					   else NoPoints

      | (Point _, LineSegment seg) => intersect(v2,v1)

      | (Line _, Point _) => intersect(v2,v1)

      | (Line (m1,b1), Line (m2,b2)) =>
	if real_close(m1,m2) 
	then (if real_close(b1,b2)
	      then v1 (* same line *)
	      else  NoPoints) (* parallel lines do not intersect *)
	else 
	    let (* one-point intersection *)
		val x = (b2 - b1) / (m1 - m2)
		val y = m1 * x + b1
	    in
		Point (x,y)
	    end

      | (Line (m1,b1), VerticalLine x2) => Point(x2, m1 * x2 + b1)

      | (Line _, LineSegment _) => intersect(v2,v1)

      | (VerticalLine _, Point _) => intersect(v2,v1)
      | (VerticalLine _, Line _)  => intersect(v2,v1)

      | (VerticalLine x1, VerticalLine x2) =>
	if real_close(x1,x2)
	then v1 (* same line *)
	else NoPoints (* parallel *)

      | (VerticalLine _, LineSegment seg) => intersect(v2,v1)

      | (LineSegment seg, _) => 
	(* the hard case, actually 4 cases because v2 could be a point,
	   line, vertical line, or line segment *)
	(* First compute the intersection of (1) the line containing the segment 
           and (2) v2. Then use that result to compute what we need. *)
	(case intersect(two_points_to_line seg, v2) of
	    NoPoints => NoPoints 
	  | Point(x0,y0) => (* see if the point is within the segment bounds *)
	    (* assumes v1 was properly preprocessed *)
	    let 
		fun inbetween(v,end1,end2) =
		    (end1 - epsilon <= v andalso v <= end2 + epsilon)
		    orelse (end2 - epsilon <= v andalso v <= end1 + epsilon)
		val (x1,y1,x2,y2) = seg
	    in
		if inbetween(x0,x1,x2) andalso inbetween(y0,y1,y2)
		then Point(x0,y0)
		else NoPoints
	    end
	  | Line _ => v1 (* so segment seg is on line v2 *)
	  | VerticalLine _ => v1 (* so segment seg is on vertical-line v2 *)
	  | LineSegment seg2 => 
	    (* the hard case in the hard case: seg and seg2 are on the same
               line (or vertical line), but they could be (1) disjoint or 
               (2) overlapping or (3) one inside the other or (4) just touching.
	       And we treat vertical segments differently, so there are 4*2 cases.
	     *)
	    let
		val (x1start,y1start,x1end,y1end) = seg
		val (x2start,y2start,x2end,y2end) = seg2
	    in
		if real_close(x1start,x1end)
		then (* the segments are on a vertical line *)
		    (* let segment a start at or below start of segment b *)
		    let 
			val ((aXstart,aYstart,aXend,aYend),
			     (bXstart,bYstart,bXend,bYend)) = if y1start < y2start
							      then (seg,seg2)
							      else (seg2,seg)
		    in
			if real_close(aYend,bYstart)
			then Point (aXend,aYend) (* just touching *)
			else if aYend < bYstart
			then NoPoints (* disjoint *)
			else if aYend > bYend
			then LineSegment(bXstart,bYstart,bXend,bYend) (* b inside a *)
			else LineSegment(bXstart,bYstart,aXend,aYend) (* overlapping *)
		    end
		else (* the segments are on a (non-vertical) line *)
		    (* let segment a start at or to the left of start of segment b *)
		    let 
			val ((aXstart,aYstart,aXend,aYend),
			     (bXstart,bYstart,bXend,bYend)) = if x1start < x2start
							      then (seg,seg2)
							      else (seg2,seg)
		    in
			if real_close(aXend,bXstart)
			then Point (aXend,aYend) (* just touching *)
			else if aXend < bXstart
			then NoPoints (* disjoint *)
			else if aXend > bXend
			then LineSegment(bXstart,bYstart,bXend,bYend) (* b inside a *)
			else LineSegment(bXstart,bYstart,aXend,aYend) (* overlapping *)
		    end	
	    end						
	  | _ => raise Impossible "bad result from intersecting with a line")
      | _ => raise Impossible "bad call to intersect: only for shape values"

(* interpreter for our language: 
   * takes a geometry expression and returns a geometry value
   * for simplicity we have the top-level function take an environment,
     (which should be [] for the whole program
   * we assume the expression e has already been "preprocessed" as described
     in the homework assignment: 
         * line segments are not actually points (endpoints not real close)
         * lines segment have left (or, if vertical, bottom) coordinate first
*)

fun eval_prog (e,env) =
    case e of
	NoPoints => e (* first 5 cases are all values, so no computation *)
      | Point _  => e
      | Line _   => e
      | VerticalLine _ => e
      | LineSegment _  => e
      | Var s => 
	(case List.find (fn (s2,v) => s=s2) env of
	     NONE => raise BadProgram("var not found: " ^ s)
	   | SOME (_,v) => v)
      | Let(s,e1,e2) => eval_prog (e2, ((s, eval_prog(e1,env)) :: env))
      | Intersect(e1,e2) => intersect(eval_prog(e1,env), eval_prog(e2, env))
      | Shift(deltaX, deltaY, e1)  => (case eval_prog(e1, env) of
				NoPoints => NoPoints
				| Point (x, y)  => Point (x + deltaX, y + deltaY)
				| Line (m, b)  => Line (m, b + deltaY - m*deltaX)
				| VerticalLine (x) => VerticalLine (x + deltaX)
				| LineSegment (x1, y1, x2, y2) => LineSegment (x1 + deltaX, y1 + deltaY, x2 + deltaX, y2 + deltaY)
				| _ => raise Impossible "bad call to Shift.")   
(* CHANGE: Add a case for Shift expressions *)

(* CHANGE: Add function preprocess_prog of type geom_exp -> geom_exp *)
fun preprocess_prog (e) = 
    case e of
	LineSegment (x1, y1, x2, y2) => if real_close_point (x1, y1) (x2, y2)
					then Point(x1, y1)
					else (if real_close(x1, x2) then (if (y1 > y2) then LineSegment(x2, y2, x1, y1) else LineSegment (x1, y1, x2, y2))
					                            else (if (x1 > x2) then LineSegment(x2, y2, x1, y1) else LineSegment (x1, y1, x2, y2)))
		| Intersect (e1, e2) => Intersect (preprocess_prog(e1), preprocess_prog(e2))
		| Let (s, e1, e2)    => Let (s, preprocess_prog(e1), preprocess_prog(e2)) 
		| Shift (deltaX, deltaY, e1) => Shift (deltaX, deltaY, preprocess_prog(e1)) 
		| _ => e

sml test

(* University of Washington, Programming Languages, Homework 7
   hw7testsprovided.sml *)
(* Will not compile until you implement preprocess and eval_prog *)

(* These tests do NOT cover all the various cases, especially for intersection *)

use "hw7.sml";

(* Must implement preprocess_prog and Shift before running these tests *)

fun real_equal(x,y) = Real.compare(x,y) = General.EQUAL;

(* Preprocess tests *)
let
	val Point(a,b) = preprocess_prog(LineSegment(3.2,4.1,3.2,4.1))
	val Point(c,d) = Point(3.2,4.1)
in
	if real_equal(a,c) andalso real_equal(b,d)
	then (print "preprocess converts a LineSegment to a Point successfully\n")
	else (print "preprocess does not convert a LineSegment to a Point succesfully\n")
end;

let 
	val LineSegment(a,b,c,d) = preprocess_prog (LineSegment(3.2,4.1,~3.2,~4.1))
	val LineSegment(e,f,g,h) = LineSegment(~3.2,~4.1,3.2,4.1)
in
	if real_equal(a,e) andalso real_equal(b,f) andalso real_equal(c,g) andalso real_equal(d,h)
	then (print "preprocess flips an improper LineSegment successfully\n")
	else (print "preprocess does not flip an improper LineSegment successfully\n")
end;

(* eval_prog tests with Shift*)
let 
	val Point(a,b) = (eval_prog (preprocess_prog (Shift(3.0, 4.0, Point(4.0,4.0))), []))
	val Point(c,d) = Point(7.0,8.0) 
in
	if real_equal(a,c) andalso real_equal(b,d)
	then (print "eval_prog with empty environment worked\n")
	else (print "eval_prog with empty environment is not working properly\n")
end;

(* Using a Var *)
let 
	val Point(a,b) = (eval_prog (Shift(3.0,4.0,Var "a"), [("a",Point(4.0,4.0))]))
	val Point(c,d) = Point(7.0,8.0) 
in
	if real_equal(a,c) andalso real_equal(b,d)
	then (print "eval_prog with 'a' in environment is working properly\n")
	else (print "eval_prog with 'a' in environment is not working properly\n")
end;


(* With Variable Shadowing *)
let 
	val Point(a,b) = (eval_prog (Shift(3.0,4.0,Var "a"), [("a",Point(4.0,4.0)),("a",Point(1.0,1.0))]))
	val Point(c,d) = Point(7.0,8.0) 
in
	if real_equal(a,c) andalso real_equal(b,d)
	then (print "eval_prog with shadowing 'a' in environment is working properly\n")
	else (print "eval_prog with shadowing 'a' in environment is not working properly\n")
end;

ruby code

# University of Washington, Programming Languages, Homework 7, hw7.rb
# (See also ML code.)

# a little language for 2D geometry objects

# each subclass of GeometryExpression, including subclasses of GeometryValue,
#  needs to respond to messages preprocess_prog and eval_prog
#
# each subclass of GeometryValue additionally needs:
#   * shift
#   * intersect, which uses the double-dispatch pattern
#   * intersectPoint, intersectLine, and intersectVerticalLine for 
#       for being called by intersect of appropriate clases and doing
#       the correct intersection calculuation
#   * (We would need intersectNoPoints and intersectLineSegment, but these
#      are provided by GeometryValue and should not be overridden.)
#   *  intersectWithSegmentAsLineResult, which is used by 
#      intersectLineSegment as described in the assignment
#
# you can define other helper methods, but will not find much need to

# Note: geometry objects should be immutable: assign to fields only during
#       object construction

# Note: For eval_prog, represent environments as arrays of 2-element arrays
# as described in the assignment

class GeometryExpression  
  # do *not* change this class definition
  Epsilon = 0.00001
end

class GeometryValue < GeometryExpression
  # do *not* change methods in this class definition
  # you can add methods if you wish

  private
  # some helper methods that may be generally useful
  def real_close(r1,r2) 
      (r1 - r2).abs < GeometryExpression::Epsilon
  end
  def real_close_point(x1,y1,x2,y2) 
      real_close(x1,x2) && real_close(y1,y2)
  end
  # two_points_to_line could return a Line or a VerticalLine
  def two_points_to_line(x1,y1,x2,y2) 
      if real_close(x1,x2)
        VerticalLine.new x1
      else
        m = (y2 - y1).to_f / (x2 - x1)
        b = y1 - m * x1
        Line.new(m,b)
      end
  end

  public
  # we put this in this class so all subclasses can inherit it:
  # the intersection of self with a NoPoints is a NoPoints object
  def intersectNoPoints np
    np # could also have NoPoints.new here instead
  end

  # we put this in this class so all subclasses can inhert it:
  # the intersection of self with a LineSegment is computed by
  # first intersecting with the line containing the segment and then
  # calling the result's intersectWithSegmentAsLineResult with the segment
  def intersectLineSegment seg
    line_result = intersect(two_points_to_line(seg.x1,seg.y1,seg.x2,seg.y2))
    line_result.intersectWithSegmentAsLineResult seg
  end
end

class NoPoints < GeometryValue
  # do *not* change this class definition: everything is done for you
  # (although this is the easiest class, it shows what methods every subclass
  # of geometry values needs)

  # Note: no initialize method only because there is nothing it needs to do
  def eval_prog env 
    self # all values evaluate to self
  end
  def preprocess_prog
    self # no pre-processing to do here
  end
  def shift(dx,dy)
    self # shifting no-points is no-points
  end
  def intersect other
    other.intersectNoPoints self # will be NoPoints but follow double-dispatch
  end
  def intersectPoint p
    self # intersection with point and no-points is no-points
  end
  def intersectLine line
    self # intersection with line and no-points is no-points
  end
  def intersectVerticalLine vline
    self # intersection with line and no-points is no-points
  end
  # if self is the intersection of (1) some shape s and (2) 
  # the line containing seg, then we return the intersection of the 
  # shape s and the seg.  seg is an instance of LineSegment
  def intersectWithSegmentAsLineResult seg
    self
  end
end


class Point < GeometryValue
  # *add* methods to this class -- do *not* change given code and do not
  # override any methods

  # Note: You may want a private helper method like the local
  # helper function inbetween in the ML code
  private 
  def inbetween(v,end1,end2)
     (end1 - GeometryExpression::Epsilon <= v and v <= end2 + GeometryExpression::Epsilon) or (end2 - GeometryExpression::Epsilon <= v and v <= end1 + GeometryExpression::Epsilon)
  end

  public
  attr_reader :x , :y
  def initialize(x,y)
    @x = x
    @y = y
  end
  def eval_prog env 
    self # all values evaluate to self
  end
  def preprocess_prog
    self # no pre-processing to do here
  end
  def shift(dx,dy)
    Point.new(@x + dx, @y + dy) # shifting a point
  end
  def intersect other
    other.intersectPoint self
  end
  def intersectPoint p
    if real_close_point(@x, @y, p.x, p.y)
       Point.new(p.x, p.y)
    else
       NoPoints.new
    end
  end
  def intersectLine line
    if real_close(@y, line.m * @x + line.b)
       Point.new(@x, @y)
    else
       NoPoints.new
    end
  end
  def intersectVerticalLine vline
    if real_close(@x, vline.x)
       Point.new(@x, @y)
    else
       NoPoints.new
    end
  end
  def intersectWithSegmentAsLineResult seg
    if (inbetween(@x,seg.x1,seg.x2) and inbetween(@y,seg.y1,seg.y2)) then
       Point.new(@x,@y)
    else
       NoPoints.new
    end
  end
end

class Line < GeometryValue
  # *add* methods to this class -- do *not* change given code and do not
  # override any methods
  attr_reader :m, :b 
  def initialize(m,b)
    @m = m
    @b = b
  end
  def eval_prog env 
    self # all values evaluate to self
  end
  def preprocess_prog
    self # no pre-processing to do here
  end
  def shift(dx,dy)
    Line.new(@m, @b + dy - @m*dx) # shifting a line
  end
  def intersect other
    other.intersectLine self
  end
  def intersectPoint p
    p.intersectLine self
  end
  def intersectLine line
    if real_close(@m, line.m) then
       if real_close(@b, line.b) then
           Line.new(@m, @b)
       else
           NoPoints.new
       end
    else
       x = (line.b - @b) / (@m - line.m)
       y = @m * x + @b
       Point.new(x, y)
    end
  end
  def intersectVerticalLine vline
    Point.new(vline.x, @m * vline.x + @b)
  end
  def intersectWithSegmentAsLineResult seg
    #Line.new(@m, @b)
	LineSegment.new(seg.x1,seg.y1,seg.x2,seg.y2)
  end
end

class VerticalLine < GeometryValue
  # *add* methods to this class -- do *not* change given code and do not
  # override any methods
  attr_reader :x 
  def initialize x
    @x = x
  end
  def eval_prog env 
    self # all values evaluate to self
  end
  def preprocess_prog
    self # no pre-processing to do here
  end
  def shift(dx,dy)
    VerticalLine.new(@x + dx) # shifting a vertical line
  end
  def intersect other
    other.intersectVerticalLine self
  end
  def intersectPoint p
    p.intersectVerticalLine self
  end
  def intersectLine line
    line.intersectVerticalLine self
  end
  def intersectVerticalLine vline
    if real_close(@x, vline.x)
        VerticalLine.new(@x)
    else
        NoPoints.new
    end
  end
  def intersectWithSegmentAsLineResult seg
    #VerticalLine.new(@x)
	LineSegment.new(seg.x1,seg.y1,seg.x2,seg.y2)	
  end
end

class LineSegment < GeometryValue
  # *add* methods to this class -- do *not* change given code and do not
  # override any methods
  # Note: This is the most difficult class.  In the sample solution,
  #  preprocess_prog is about 15 lines long and 
  # intersectWithSegmentAsLineResult is about 40 lines long
  attr_reader :x 1, :y1, :x 2, :y2
  def initialize (x1,y1,x2,y2)
    @x1 = x1
    @y1 = y1
    @x2 = x2
    @y2 = y2
  end
  def eval_prog env 
    self # all values evaluate to self
  end
  def preprocess_prog
    if real_close_point(@x1,@y1,@x2,@y2) then
       Point.new(@x1,@y1)
    else
       if real_close(@x1,@x2) then
           if (@y1>@y2) then 
               LineSegment.new(@x2,@y2,@x1,@y1) 
           else 
               LineSegment.new(@x1,@y1,@x2,@y2) 
           end
       else
           if (x1>x2) then 
               LineSegment.new(@x2,@y2,@x1,@y1) 
           else 
               LineSegment.new(@x1,@y1,@x2,@y2) 
           end
       end
    end
  end
  def shift(dx,dy)
    LineSegment.new(@x1 + dx,@y1 + dy,@x2 + dx,@y2 + dy) 
  end
  def intersect other
    other.intersectLineSegment self.preprocess_prog
  end
  def intersectPoint p
    p.intersectLineSegment self
  end
  def intersectLine line
    line.intersectLineSegment self
  end
  def intersectVerticalLine vline
    vline.intersectLineSegment self
  end
  def intersectWithSegmentAsLineResult seg
    x1start = seg.x1
    y1start = seg.y1
    x1end = seg.x2
    y1end = seg.y2
    x2start = @x1
    y2start = @y1
    x2end = @x2
    y2end = @y2

    if real_close(x1start,x1end) then
        if y1start < y2start then
            aXstart = seg.x1
            aYstart = seg.y1
            aXend = seg.x2
            aYend = seg.y2
            bXstart = @x1
            bYstart = @y1
            bXend = @x2
            bYend = @y2
        else
            aXstart = @x1
            aYstart = @y1
            aXend = @x2
            aYend = @y2
            bXstart = seg.x1
            bYstart = seg.y1
            bXend = seg.x2
            bYend = seg.y2
        end
        if real_close(aYend,bYstart) then
            Point.new(aXend,aYend)
        elsif aYend < bYstart then
            NoPoints.new
        elsif aYend > bYend then
            LineSegment.new(bXstart,bYstart,bXend,bYend)
        else
            LineSegment.new(bXstart,bYstart,aXend,aYend)
        end
    else
        if x1start < x2start then
            aXstart = seg.x1
            aYstart = seg.y1
            aXend = seg.x2
            aYend = seg.y2
            bXstart = @x1
            bYstart = @y1
            bXend = @x2
            bYend = @y2
        else
            aXstart = @x1
            aYstart = @y1
            aXend = @x2
            aYend = @y2
            bXstart = seg.x1
            bYstart = seg.y1
            bXend = seg.x2
            bYend = seg.y2
        end
        if real_close(aXend,bXstart) then
            Point.new(aXend,aYend)
        elsif aXend < bXstart then
            NoPoints.new
        elsif aXend > bXend then
            LineSegment.new(bXstart,bYstart,bXend,bYend)
        else
            LineSegment.new(bXstart,bYstart,aXend,aYend)
        end
    end
  end
end

# Note: there is no need for getter methods for the non-value classes

class Intersect < GeometryExpression
  # *add* methods to this class -- do *not* change given code and do not
  # override any methods
  def initialize(e1,e2)
    @e1 = e1
    @e2 = e2
  end
  def eval_prog env 
    (@e1.eval_prog(env)).intersect(@e2.eval_prog(env))
  end
  def preprocess_prog
    Intersect.new(@e1.preprocess_prog,@e2.preprocess_prog)
  end
end

class Let < GeometryExpression
  # *add* methods to this class -- do *not* change given code and do not
  # override any methods
  def initialize(s,e1,e2)
    @s = s
    @e1 = e1
    @e2 = e2
  end
  def eval_prog env 
	@e2.eval_prog([[@s, @e1.eval_prog(env)]] + env)
  end
  def preprocess_prog
    Let.new(@s,@e1.preprocess_prog,@e2.preprocess_prog)
  end    
end

class Var < GeometryExpression
  # *add* methods to this class -- do *not* change given code and do not
  # override any methods
  def initialize s
    @s = s
  end
  def eval_prog env 
	env.find{|x| x[0] == @s}[1]
  end
  def preprocess_prog
    self
  end      
end

class Shift < GeometryExpression
  # *add* methods to this class -- do *not* change given code and do not
  # override any methods
  def initialize(dx,dy,e)
    @dx = dx
    @dy = dy
    @e = e
  end
  def eval_prog env 
    (@e.eval_prog(env)).shift(@dx,@dy)
  end
  def preprocess_prog
    Shift.new(@dx,@dy,@e.preprocess_prog)
  end  
end

ruby tests

# University of Washington, Programming Languages, Homework 7, 
# hw7testsprovided.rb

require "./hw7a.rb"

#  Will not work completely until you implement all the classes and their methods

# Will print only if code has errors; prints nothing if all tests pass

# These tests do NOT cover all the various cases, especially for intersection

#Constants for testing
ZERO = 0.0
ONE = 1.0
TWO = 2.0
THREE = 3.0
FOUR = 4.0
FIVE = 5.0
SIX = 6.0
SEVEN = 7.0
TEN = 10.0

#Point Tests
a = Point.new(THREE,FIVE)
if not (a.x == THREE and a.y == FIVE)
	puts "Point is not initialized properly"
end
if not (a.eval_prog([]) == a)
	puts "Point eval_prog should return self"
end
if not (a.preprocess_prog == a)
	puts "Point preprocess_prog should return self"
end
a1 = a.shift(THREE,FIVE)
if not (a1.x == SIX and a1.y == TEN)
	puts "Point shift not working properly"
end
a2 = a.intersect(Point.new(THREE,FIVE))
if not (a2.x == THREE and a2.y == FIVE)
	puts "Point intersect not working properly"
end 
a3 = a.intersect(Point.new(FOUR,FIVE))
if not (a3.is_a? NoPoints)
	puts "Point intersect not working properly"
end

#Line Tests
b = Line.new(THREE,FIVE)
if not (b.m == THREE and b.b == FIVE)
	puts "Line not initialized properly"
end
if not (b.eval_prog([]) == b)
	puts "Line eval_prog should return self"
end
if not (b.preprocess_prog == b)
	puts "Line preprocess_prog should return self"
end

b1 = b.shift(THREE,FIVE) 
if not (b1.m == THREE and b1.b == ONE)
	puts "Line shift not working properly"
end

b2 = b.intersect(Line.new(THREE,FIVE))
if not (((b2.is_a? Line)) and b2.m == THREE and b2.b == FIVE)
	puts "Line intersect not working properly"
end
b3 = b.intersect(Line.new(THREE,FOUR))
if not ((b3.is_a? NoPoints))
	puts "Line intersect not working properly"
end

#VerticalLine Tests
c = VerticalLine.new(THREE)
if not (c.x == THREE)
	puts "VerticalLine not initialized properly"
end

if not (c.eval_prog([]) == c)
	puts "VerticalLine eval_prog should return self"
end
if not (c.preprocess_prog == c)
	puts "VerticalLine preprocess_prog should return self"
end
c1 = c.shift(THREE,FIVE)
if not (c1.x == SIX)
	puts "VerticalLine shift not working properly"
end
c2 = c.intersect(VerticalLine.new(THREE))
if not ((c2.is_a? VerticalLine) and c2.x == THREE )
	puts "VerticalLine intersect not working properly"
end
c3 = c.intersect(VerticalLine.new(FOUR))
if not ((c3.is_a? NoPoints))
	puts "VerticalLine intersect not working properly"
end

#LineSegment Tests
d = LineSegment.new(ONE,TWO,-THREE,-FOUR)
if not (d.eval_prog([]) == d)
	puts "LineSegement eval_prog should return self"
end
d1 = LineSegment.new(ONE,TWO,ONE,TWO)
d2 = d1.preprocess_prog
if not ((d2.is_a? Point)and d2.x == ONE and d2.y == TWO) 
	puts "LineSegment preprocess_prog should convert to a Point"
	puts "if ends of segment are real_close"
end

d = d.preprocess_prog
if not (d.x1 == -THREE and d.y1 == -FOUR and d.x2 == ONE and d.y2 == TWO)
	puts "LineSegment preprocess_prog should make x1 and y1"
	puts "on the left of x2 and y2"
end

d3 = d.shift(THREE,FIVE)
if not (d3.x1 == ZERO and d3.y1 == ONE and d3.x2 == FOUR and d3.y2 == SEVEN)
	puts "LineSegment shift not working properly"
end

d4 = d.intersect(LineSegment.new(-THREE,-FOUR,ONE,TWO))
if not (((d4.is_a? LineSegment)) and d4.x1 == -THREE and d4.y1 == -FOUR and d4.x2 == ONE and d4.y2 == TWO)	
	puts "LineSegment intersect not working properly"
end
d5 = d.intersect(LineSegment.new(TWO,THREE,FOUR,FIVE))
if not ((d5.is_a? NoPoints))
	puts "LineSegment intersect not working properly"
end

#Intersect Tests
i = Intersect.new(LineSegment.new(-ONE,-TWO,THREE,FOUR), LineSegment.new(THREE,FOUR,-ONE,-TWO))
i1 = i.preprocess_prog.eval_prog([])
if not (i1.x1 == -ONE and i1.y1 == -TWO and i1.x2 == THREE and i1.y2 == FOUR)
	puts "Intersect eval_prog should return the intersect between e1 and e2"
end

#Var Tests
v = Var.new("a")
v1 = v.eval_prog([["a", Point.new(THREE,FIVE)]])
if not ((v1.is_a? Point) and v1.x == THREE and v1.y == FIVE)
	puts "Var eval_prog is not working properly"
end 
if not (v1.preprocess_prog == v1)
	puts "Var preprocess_prog should return self"
end

#Let Tests
l = Let.new("a", LineSegment.new(-ONE,-TWO,THREE,FOUR),
             Intersect.new(Var.new("a"),LineSegment.new(THREE,FOUR,-ONE,-TWO)))
l1 = l.preprocess_prog.eval_prog([])
if not (l1.x1 == -ONE and l1.y1 == -TWO and l1.x2 == THREE and l1.y2 == FOUR)
	puts "Let eval_prog should evaluate e2 after adding [s, e1] to the environment"
end

#Let Variable Shadowing Test
l2 = Let.new("a", LineSegment.new(-ONE, -TWO, THREE, FOUR),
              Let.new("b", LineSegment.new(THREE,FOUR,-ONE,-TWO), Intersect.new(Var.new("a"),Var.new("b"))))
l2 = l2.preprocess_prog.eval_prog([["a",Point.new(0,0)]])
if not (l2.x1 == -ONE and l2.y1 == -TWO and l2.x2 == THREE and l2.y2 == FOUR)
	puts "Let eval_prog should evaluate e2 after adding [s, e1] to the environment"
end


#Shift Tests
s = Shift.new(THREE,FIVE,LineSegment.new(-ONE,-TWO,THREE,FOUR))
s1 = s.preprocess_prog.eval_prog([])
if not (s1.x1 == TWO and s1.y1 == THREE and s1.x2 == SIX and s1.y2 == 9)
	puts "Shift should shift e by dx and dy"
end






Ownership Parcel ID conversion from Integer to String

$
0
0

It is required to convert the ID from an integer to a string with length of 9.

Right(str([IDENT] + 1000000000), 9)


Computational Photography Programming Assignment 0 – Image

$
0
0
import sys
import os
import numpy as np
import cv2

def split_rgb(image):
  '''Split the target image into its red, green and blue channels.
  
  image - a numpy array of shape (rows, columns, 3).
  output - three numpy arrays of shape (rows, columns) and dtype same as
           image, containing the corresponding channels. 
  
  Please make sure the output shape has only 2 components!
  For instance, (600, 800) instead of (600, 800, 1)
  '''
  red = None
  green = None
  blue = None
  # Insert your code here.----------------------------------------------------
  blue = image[:, :, 0]
  green = image[:, :, 1]
  red = image[:, :, 2]
  #---------------------------------------------------------------------------
  return red, green, blue

def main():
  ''' This function applies your split script to images.

  It will search through the images/part0 subfolder, and apply your splitting 
  function to each one. It will then save the resulting images.
  '''
  imagesfolder0 = os.path.abspath(os.path.join(os.curdir, 'images', 'part0'))
  print '''Searching for images in {} folder
  (will ignore red, green, or blue in the name)'''.format(imagesfolder0)

  exts = ['.bmp', '.pbm', '.pgm', '.ppm', '.sr', '.ras', '.jpeg', '.jpg', 
    '.jpe', '.jp2', '.tiff', '.tif', '.png']

  for dirname, dirnames, filenames in os.walk(imagesfolder0):
    for filename in filenames:
      name, ext = os.path.splitext(filename)
      if ext in exts and 'red' not in name and 'green' not in name and \
        'blue' not in name:
        print "Splitting image {}.".format(filename)

        img = cv2.imread(os.path.join(dirname, filename))
        red, green, blue = split_rgb(img)

        for values, color, channel in zip((red, green, blue), 
            ('red', 'green', 'blue'), (2,1,0)):
          img = np.zeros((values.shape[0], values.shape[1], 3), 
              dtype = values.dtype) 
          img[:,:,channel] = values
          print "Writing image {}.".format(name+color+ext)
          cv2.imwrite(os.path.join(dirname, name+color+ext), img)

def test():
  '''This script will perform a unit test on your function, and provide useful
  output.
  '''
  x = (np.random.rand(4,4,3) * 255).astype(np.uint8)

  if __name__ == "__main__":
    print "Input:\n{}".format(x)

  usr_red, usr_green, usr_blue = split_rgb(x)

  true_red = x[:,:,2]
  true_green = x[:,:,1]
  true_blue = x[:,:,0]

  for usr_out, true_out, name in zip((usr_red, usr_green, usr_blue),
      (true_red, true_green, true_blue), ('red', 'green', 'blue')):

    if usr_out == None:
      if __name__ == "__main__":
        print "Error- {} has value None.".format(name)
      return False

    if not usr_out.shape == true_out.shape:
      if __name__ == "__main__":
        print "Error- {} has shape {}. Expected shape is {}.".format(name,
            usr_out.shape, true_out.shape)
      return False

    if not usr_out.dtype == true_out.dtype:
      if __name__ == "__main__":
        print "Error- {} has dtype {}. Expected dtype is {}.".format(name,
            usr_out.dtype, true_out.dtype)
      return False

    if not np.all(usr_out == true_out):
      if __name__ == "__main__":
        print "Error- {} has value:\n{}\nExpected value:\n{}".format(name,
            usr_out, true_out)
      return False

  if __name__ == "__main__":
    print "Success - all outputs correct."
  return True

if __name__ == "__main__":
  # Testing code
  print "Performing unit test."
  t = test()
  print "Unit test: {}".format(t)
  if t:
    main()
import sys, os
import numpy as np
import cv2

def interlace(evens, odds):
  '''Reconstruct the image by alternating rows of evens and odds.

  evens - a numpy array of shape (rows, columns, 3)  containing the even rows 
          of the output image.
  odds - a numpy array of shape (rows, columns, 3) containing the odd rows 
         of the output image.

  This function should return an image. Row 0 of the output image should be
  row 0 of evens. Row 1 of the output image should be row 0 of odds. Then
  row 1 of evens, then row 1 of odds, and so on.

  The resulting image will have as many rows as image 1 and 2 combined, equal
  to both in number of columns, and have 3 channels.
  '''

  outimg = None
  # Implement your function here ---------------------------------------------
  size = evens.shape
  outimg = np.zeros( (size[0]*2, size[1], size[2]), 'uint8' )
  for i in range(size[0]):
    outimg[2*i,:, :] = evens[i, :, :]
    outimg[2*i + 1,:, :] = odds[i, :, :]
  #---------------------------------------------------------------------------
  return outimg

def main():
  ''' This code will attempt to reconstruct the images in the images/part1
  folder, and save the output.
  '''
  imagesfolder = os.path.join('images', 'part1')
  print "part 1 : attempting to interlace images evens.jpg and odds.jpg"

  evens = cv2.imread(os.path.join(imagesfolder, 'even.jpg'))
  odds = cv2.imread(os.path.join(imagesfolder, 'odd.jpg'))

  if evens == None or odds == None:
    print "Error - could not find even.jpg and odd.jpg in {}".format(imagesfolder)
    sys.exit(0)

  together = interlace(evens, odds)

  if not together == None:
    cv2.imwrite(os.path.join(imagesfolder, 'together.jpg'), together)

def test():
  '''This script will perform a unit test on your function, and provide useful
  output.
  '''
  x = (np.random.rand(4,4,3) * 255).astype(np.uint8)

  xeven = x[np.arange(0,x.shape[0], 2), :, :]
  xodd  = x[np.arange(1,x.shape[0], 2), :, :]

  if __name__== "__main__":
    print "Input:\n  even:\n{}\n  odd:\n{}".format(xeven, xodd)

  usr_out = interlace(xeven, xodd)

  if usr_out == None:
    if __name__ == "__main__":
      print "Error- output has value None."
    return False

  if not usr_out.shape == x.shape:
    if __name__ == "__main__":
      print "Error- output has shape {}. Expected shape is {}.".format(
          usr_out.shape, x.shape)
    return False

  if not usr_out.dtype == x.dtype:
    if __name__ == "__main__":
      print "Error- output has dtype {}. Expected dtype is {}.".format(
          usr_out.dtype, x.dtype)
    return False

  if not np.all(usr_out == x):
    if __name__ == "__main__":
      print "Error- output has value:\n{}\nExpected value:\n{}".format(
          usr_out, x)
    return False

  if __name__ == "__main__":
    print "Success - all outputs correct."
  return True

if __name__ == "__main__":
  # Testing code
  t = test()
  print "Unit test: {}".format(t)
  if t:
    main()
import sys
import os
import numpy as np
import cv2

def greyscale(image):
  '''Convert an image to greyscale.
  
  image  - a numpy array of shape (rows, columns, 3).
  output - a numpy array of shape (rows, columns) and dtype same as
           image, containing the average of image's 3 channels. 
  
  Please make sure the output shape has only 2 components!
  For instance, (512, 512) instead of (512, 512, 1)
  '''
  output = None
  # Insert your code here.----------------------------------------------------
  output = (image.sum(2)/3).astype(np.uint8)
  #---------------------------------------------------------------------------
  return output

def main():
  '''Convert images to greyscale.

  It will search through the images/part2 subfolder, and apply your function
  to each one, saving the output image in the same folder.
  '''

  imagesfolder = os.path.join('images', 'part2')

  print '''part 2 : Searching for images in {} folder
  (will ignore if grey in the name)'''.format(imagesfolder)

  exts = ['.bmp', '.pbm', '.pgm', '.ppm', '.sr', '.ras', '.jpeg', '.jpg', 
    '.jpe', '.jp2', '.tiff', '.tif', '.png']

  for dirname, dirnames, filenames in os.walk(imagesfolder):
    for filename in filenames:
      name, ext = os.path.splitext(filename)
      if ext in exts and 'grey' not in name:
        print "Attempting to split image {}.".format(filename)

        img = cv2.imread(os.path.join(dirname, filename))
        grey = greyscale(img)
        print "Writing image {}".format(name+"grey"+ext)
        cv2.imwrite(os.path.join(dirname, name+"grey"+ext), grey)

def test():
  '''This script will perform a unit test on your function, and provide useful
  output.
  '''
  x = (np.random.rand(4,4,3) * 255).astype(np.uint8)

  if __name__ == "__main__":
    print "Input:\n{}".format(x)

  usr_grey = greyscale(x)
  true_grey = (x.sum(2)/3).astype(np.uint8)

  if usr_grey == None:
    if __name__ == "__main__":
      print "Error- output has value None."
    return False

  if not usr_grey.shape == true_grey.shape:
    if __name__ == "__main__":
      print "Error- output has shape {}. Expected shape is {}.".format(
          usr_grey.shape, true_grey.shape)
    return False

  if not usr_grey.dtype == true_grey.dtype:
    if __name__ == "__main__":
      print "Error- output has dtype {}. Expected dtype is {}.".format(
          usr_grey.dtype, true_grey.dtype)
    return False

  if not np.all(usr_grey == true_grey):
    if __name__ == "__main__":
      print "Error- output has value:\n{}\nExpected value:\n{}".format(
          usr_grey, true_grey)
    return False

  if __name__ == "__main__":
    print "Success - all outputs correct."
  return True

if __name__ == "__main__":
  # Testing code
  t = test()
  print "Unit test - {}".format(t)
  if t:
    main()

Learn to Program: Crafting Quality Code Assignment 1

$
0
0
def num_buses(n):
    """ (int) -> int

    Precondition: n >= 0

    Return the minimum number of buses required to transport n people.
    Each bus can hold 50 people.

    >>> num_buses(75)
    2
    """
    if not (type(n) is int):
        raise ValueError('n must be int')    
    if n < 0:
        raise ValueError('n must be >= 0')
    if (n % 50 == 0):
        return n/50
    else:
        return n/50 + 1

def stock_price_summary(price_changes):
    """ (list of number) -> (number, number) tuple

    price_changes contains a list of stock price changes. Return a 2-item
    tuple where the first item is the sum of the gains in price_changes and
    the second is the sum of the losses in price_changes.

    >>> stock_price_summary([0.01, 0.03, -0.02, -0.14, 0, 0, 0.10, -0.01])
    (0.14, -0.17)
    """
    gains = 0
    losses = 0
    for price_change in price_changes:
        if price_change > 0:
            gains = gains + price_change
        else:
            losses = losses + price_change
    return (gains, losses)
def swap_k(L, k):
    """ (list, int) -> NoneType

    Precondtion: 0 <= k <= len(L) // 2

    Swap the first k items of L with the last k items of L.

    >>> nums = [1, 2, 3, 4, 5, 6]
    >>> swap_k(nums, 2)
    >>> nums
    [5, 6, 3, 4, 1, 2]
    """
    if k < 0 or k> len(L) // 2:
        raise ValueError('k must be 0 <= k <= len(L) // 2')
    for i in range(k):
        temp = L[i]
        L[i] = L[len(L) - k + i]
        L[len(L) - k + i] = temp
        
if __name__ == '__main__':
    import doctest
    doctest.testmod()

import a1
import unittest


class TestNumBuses(unittest.TestCase):
    """ Test class for function a1.num_buses. """

    # Add your test methods for a1.num_buses here.
    def test_num_buses_with_regular_integer(self):
        """Test num_buses with regular integer."""
        actual = a1.num_buses(75)
        expected = 2
        self.assertEqual(expected, actual)    

    def test_num_buses_with_integer_50(self):
        """Test num_buses with 50. The function should return 1."""
        actual = a1.num_buses(50)
        expected = 1
        self.assertEqual(expected, actual)    
        
    def test_num_buses_with_zero(self):    
        """Test num_buses with 0. The function should return 0."""
        actual = a1.num_buses(0)
        expected = 0
        self.assertEqual(expected, actual)    

    def test_num_buses_with_negative_integer(self):    
        """Test num_buses with negative integer. A error should be raised."""
        self.assertRaises(ValueError, a1.num_buses, -1)        

    def test_num_buses_with_non_integer(self):    
        """Test num_buses with non integer. A error should be raised."""
        self.assertRaises(ValueError, a1.num_buses, 1.1)        

if __name__ == '__main__':
    unittest.main(exit=False)

import a1
import unittest


class TestStockPriceSummary(unittest.TestCase):
    """ Test class for function a1.stock_price_summary. """

    # Add your test methods for a1.stock_price_summary here.
    def test_stock_price_summary_1(self):
        """Test stock_price_summary with regular integer list."""
        actual = a1.stock_price_summary([0.01, 0.03, -0.02, -0.14, 0, 0, 0.10, -0.01])
        expected = (0.14, -0.17)
        self.assertAlmostEqual(expected[0], actual[0])
        self.assertAlmostEqual(expected[1], actual[1])
		
    def test_stock_price_summary_2(self):
        """Test stock_price_summary with empty list."""
        actual = a1.stock_price_summary([])
        expected = (0, 0)
        self.assertAlmostEqual(expected[0], actual[0])
        self.assertAlmostEqual(expected[1], actual[1])
        
    def test_stock_price_summary_3(self):    
        """Test stock_price_summary with a list full of 0."""
        actual = a1.stock_price_summary([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
        expected = (0, 0)
        self.assertAlmostEqual(expected[0], actual[0])
        self.assertAlmostEqual(expected[1], actual[1])
        
    def test_stock_price_summary_4(self):    
        """Test stock_price_summary with a list with non-positive values."""
        actual = a1.stock_price_summary([-0.01, -0.03, -0.02, -0.14, 0, 0, -0.10, -0.01])
        expected = (0, -0.31)
        self.assertAlmostEqual(expected[0], actual[0])
        self.assertAlmostEqual(expected[1], actual[1])

    def test_stock_price_summary_5(self):    
        """Test stock_price_summary with a list with non-negative values."""
        actual = a1.stock_price_summary([0.01, 0.03, 0.02, 0.14, 0.1, 0.02, 0.10, 0.01])
        expected = (0.43, 0)
        self.assertAlmostEqual(expected[0], actual[0])
        self.assertAlmostEqual(expected[1], actual[1])

if __name__ == '__main__':
    unittest.main(exit=False)

import a1
import unittest


class TestSwapK(unittest.TestCase):
    """ Test class for function a1.swap_k. """

    # Add your test methods for a1.swap_k here.
    def test_swap_k_regular_list_integer(self):
        """Test swap_k with regular list and integer."""
        actual = [1, 2, 3, 4, 5, 6]
        a1.swap_k(actual, 2)
        expected = [5, 6, 3, 4, 1, 2]
        self.assertEqual(expected, actual)    

    def test_swap_k_empty_list_zero(self):
        """Test swap_k with empty list and 0."""
        actual = []
        a1.swap_k(actual, 0)
        expected = []
        self.assertEqual(expected, actual)    
        
    def test_swap_k_regular_list_zero(self):    
        """Test swap_k with regular list and 0. The list should not change."""
        actual = [1, 2, 3, 4, 5, 6]
        a1.swap_k(actual, 0)
        expected = [1, 2, 3, 4, 5, 6]
        self.assertEqual(expected, actual)    

    def test_swap_k_4(self):    
        """Test swap_k with a regular list and a negative integer. The function should raise an error """
        self.assertRaises(ValueError, a1.swap_k, [1, 2, 3, 4, 5, 6], -1)        

    def test_swap_k_5(self):    
        """Test swap_k with a regular list and an integer which is larger than half of the size of the list."""
        """The function should raise an error."""		
        self.assertRaises(ValueError, a1.swap_k, [1, 2, 3, 4, 5, 6], 4) 

    def test_swap_k_7(self):
        """Test swap_k with a regular string list and a regular integer."""
        actual = ['a', 'b', 'c', 'd', 'e', 'f']
        a1.swap_k(actual, 3)
        expected = ['d', 'e', 'f', 'a', 'b', 'c']
        self.assertEqual(expected, actual)    
        
if __name__ == '__main__':
    unittest.main(exit=False)


Algorithms, Part II Assignment 2

$
0
0

Programming Assignment 2: Seam Carving

Warning: this assignment has not been battle-tested. It is likely that there are more ambiguities and bugs. Please bring those to our attention and we will do our best to clarify and fix.
Seam-carving is a content-aware image resizing technique where the image is reduced in size by one pixel of height (or width) at a time. A vertical seam in an image is a path of pixels connected from the top to the bottom with one pixel in each row. (Ahorizontal seam is a path of pixels connected from the left to the right with one pixel in each column.) Below left is the original 505-by-287 pixel image; below right is the result after removing 150 vertical seams, resulting in a 30% narrower image. Unlike standard content-agnostic resizing techniques (e.g. cropping and scaling), the most interesting features (aspect ratio, set of objects present, etc.) of the image are preserved.

As you’ll soon see, the underlying algorithm is quite simple and elegant. Despite this fact, this technique was not discovered until 2007 by Shai Avidan and Ariel Shamir. It is now a feature in Adobe Photoshop (thanks to a Princeton graduate student), as well as other popular computer graphics applications.

 

Dr. Hug in the ocean Dr. Hug in the oceanIn this assignment, you will create a data type that resizes a W-by-H image using the seam-carving technique.

Finding and removing a seam involves three parts and a tiny bit of notation:

    1. Notation. In image processing, pixel (xy) refers to the pixel in column x and row y, with pixel (0, 0) at the upper left corner and pixel (W − 1, H − 1) at the bottom right corner. This is consistent with the Picture data type in stdlib.jarWarning: this is the opposite of the standard mathematical notation used in linear algebra where (ij) refers to row i and column j and with Cartesian coordinates where (0, 0) is at the lower left corner. 
      a 3-by-4 image
        (0, 0)   (1, 0)   (2, 0)
        (0, 1)   (1, 1)   (2, 1)
        (0, 2)   (1, 2)   (2, 2)
        (0, 3)   (1, 3)   (2, 3)

      We also assume that the color of a pixel is represented in RGB space, using three integers between 0 and 255. This is consistent with the java.awt.Color data type.

       

    2. Energy calculation. The first step is to calculate the energy of each pixel, which is a measure of the importance of each pixel—the higher the energy, the less likely that the pixel will be included as part of a seam (as we’ll see in the next step). In this assignment, you will implement the dual gradient energy function, which is described below. Here is the dual gradient of the surfing image above: 

      Dr. Hug as energyThe energy is high (white) for pixels in the image where there is a rapid color gradient (such as the boundary between the sea and sky and the boundary between the surfing Josh Hug on the left and the ocean behind him). The seam-carving technique avoids removing such high-energy pixels.

 

    1. Seam identification. The next step is to find a vertical seam of minimum total energy. This is similar to the classic shortest path problem in an edge-weighted digraph except for the following: 
      • The weights are on the vertices instead of the edges. 
      • We want to find the shortest path from any of W pixels in the top row to any of the W pixels in the bottom row. 
      • The digraph is acyclic, where there is a downward edge from pixel (xy) to pixels (x − 1, y + 1), (xy + 1), and (x + 1, y + 1), assuming that the coordinates are in the prescribed range.

       

      Vertical Seam

 

  1. Seam removal. The final step is remove from the image all of the pixels along the seam.

The SeamCarver API. Your task is to implement the following mutable data type:

public class SeamCarver {
   public SeamCarver(Picture picture)
   public Picture picture()                       // current picture
   public     int width()                         // width of current picture
   public     int height()                        // height of current picture
   public  double energy(int x, int y)            // energy of pixel at column x and row y
   public   int[] findHorizontalSeam()            // sequence of indices for horizontal seam
   public   int[] findVerticalSeam()              // sequence of indices for vertical seam
   public    void removeHorizontalSeam(int[] a)   // remove horizontal seam from picture
   public    void removeVerticalSeam(int[] a)     // remove vertical seam from picture
}
  • Computing the energy of a pixel. We will use the dual gradient energy function: The energy of pixel (xy) is Δx2(xy) + Δy2(xy), where the square of the x-gradient Δx2(xy) = Rx(xy)2 + Gx(xy)2 + Bx(xy)2, and where the central differencesRx(xy), Gx(xy), and Bx(xy) are the absolute value in differences of red, green, and blue components between pixel (x + 1, y) and pixel (x − 1, y). The square of the y-gradient Δy2(xy) is defined in an analogous manner. We define the energy of pixels at the border of the image to be 2552 + 2552 + 2552 = 195075.As an example, consider the 3-by-4 image with RGB values (each component is an integer between 0 and 255) as shown in the table below.
      (255, 101, 51)   (255, 101, 153)   (255, 101, 255)
      (255,153,51)   (255,153,153)   (255,153,255)
      (255,203,51)   (255,204,153)   (255,205,255)
      (255,255,51)   (255,255,153)   (255,255,255)

     

    The ten border pixels have energy 195075. Only the pixels (1, 1) and (1, 2) are nontrivial. We calculate the energy of pixel (1, 2) in detail:

    Rx(1, 2) = 255 − 255 = 0,
    Gx(1, 2) = 205 − 203 = 2,
    Bx(1, 2) = 255 − 51 = 204,
    yielding Δx2(1, 2) = 22 + 2042 = 41620.

    Ry(1, 2) = 255 − 255 = 0,
    Gy(1, 2) = 255 − 153 = 102,
    By(1, 2) = 153 − 153 = 0,
    yielding Δy2(1, 2) = 1022 = 10404.

    Thus, the energy of pixel (1, 2) is 41620 + 10404 = 52024. Similarly, the energy of pixel (1, 1) is 2042 + 1032 = 52225.

     195075.0  195075.0  195075.0
     195075.0  52225.0  195075.0
     195075.0  52024.0  195075.0
     195075.0  195075.0  195075.0
  • Finding a vertical seam. The findVerticalSeam() method should return an array of length H such that entry x is the column number of the pixel to be removed from row x of the image. For example, consider the 6-by-5 image below (supplied as 6×5.png).
     ( 97, 82,107)  (220,172,141)  (243, 71,205)  (129,173,222)  (225, 40,209)  ( 66,109,219)
     (181, 78, 68)  ( 15, 28,216)  (245,150,150)  (177,100,167)  (205,205,177)  (147, 58, 99)
     (196,224, 21)  (166,217,190)  (128,120,162)  (104, 59,110)  ( 49,148,137)  (192,101, 89)
     ( 83,143,103)  (110, 79,247)  (106, 71,174)  ( 92,240,205)  (129, 56,146)  (121,111,147)
     ( 82,157,137)  ( 92,110,129)  (183,107, 80)  ( 89, 24,217)  (207, 69, 32)  (156,112, 31)

    The corresponding pixel energies are shown below, with a minimum energy vertical seam highlighted in red. In this case, the method findVerticalSeam() should return the array { 2, 3, 3, 3, 2}. 

    195075.0 195075.0 195075.0 195075.0 195075.0 195075.0
    195075.0 23346.0 51304.0 31519.0 55112.0 195075.0
    195075.0 47908.0 61346.0 35919.0 38887.0 195075.0
    195075.0 31400.0 37927.0 14437.0 63076.0 195075.0
    195075.0 195075.0 195075.0 195075.0 195075.0 195075.0

    When there are multiple vertical seams with minimal total energy, your method can return any such seam.

  • Finding a horizontal seam. The behavior of findHorizontalSeam() as analogous to that of findVerticalSeam() except that it should return an array of W such that entry y is the row number of the pixel to be removed from column y of the image.
  • Performance requirements. The width()height(), and energy() methods should take constant time in the worst case. All other methods should run in time at most proportional to W H in the worst case. For faster performance, do not construct an explicit EdgeWeightedDigraph object.
  • Exceptions. Your code should throw an exception when called with invalid arguments.

     

    • By convention, the indices x and y are integers between 0 and W − 1 and between 0 and H − 1 respectively. Throw a java.lang.IndexOutOfBoundsException if either x or y is outside its prescribed range. 
    • Throw a java.lang.IllegalArgumentException if removeVerticalSeam() or removeHorizontalSeam() is called with an array of the wrong length or if the array is not a valid seam (i.e., two consecutive entries differ by more than 1). 
    • Throw a java.lang.IllegalArgumentException if either removeVerticalSeam() or removeHorizontalSeam() is called when either the width or height is less than or equal to 1.

Analysis of running time (optional and not graded).

 

  • Give the worst-case running time to remove R rows and C columns from a W-by-H image as a function of RCW, and H
  • Estimate empirically the running time (in seconds) to remove R rows and C columns from a W-by-H image as a function of RCW, and H. Use tilde notation to simplify your answer.

Submission.  Submit SeamCarver.java, and any other files needed by your program (excluding those in stdlib.jar and algs4.jar).

 

This assignment was developed by Josh Hug, Maia Ginsburg, and Kevin Wayne.
 
 
import java.awt.Color;
import java.util.Iterator;


public class SeamCarver {
    private Picture picture;
    public SeamCarver(Picture picture) {
        this.picture = picture;       
    }
    
    private int [] findSeam(boolean isVertical) {
        //int m = (isVertical) ? picture.width() : picture.height();
        //int n = (isVertical) ? picture.height() : picture.width();
        int m = 0;
        int n = 0;
        if (isVertical) {
            m = picture.width();
            n = picture.height();
        } else {
            m = picture.height();
            n = picture.width();
        }
        
        EdgeWeightedDigraph graph = new EdgeWeightedDigraph(m * n + 2);
        for (int y = 0; y < n - 1; y++) {
            for (int x = 0; x < m; x++) {
                int nodeId = y * m + x;
                //double engery = (isVertical) ? energy(x, y) : energy(y, x);
                double engery = 0;
                if (isVertical) {
                    engery = energy(x, y);
                } else {
                    engery = energy(y, x);
                }
                int nextNodeId;
                DirectedEdge edge;
                if (x < n) {
                    nextNodeId = (y + 1) * m + x + 1;
                    edge = new DirectedEdge(nodeId, nextNodeId, engery);
                    graph.addEdge(edge);
                }                              
                nextNodeId = (y + 1) * m + x;
                edge = new DirectedEdge(nodeId, nextNodeId, engery);               
                graph.addEdge(edge);
                if (x > 0) {
                    nextNodeId = (y + 1) * m + x - 1;
                    edge = new DirectedEdge(nodeId, nextNodeId, engery);
                    graph.addEdge(edge);
                }
                
            }
        }
        //System.out.println(graph);
        for (int x = 0; x < m; x++) {
            int startNode = m*n; 
            DirectedEdge edge = new DirectedEdge(startNode, x, 0);
            graph.addEdge(edge);
        }
        //System.out.println(graph);
        for (int x = 0; x < m; x++) {
            int nextNodeId = (n - 1) * m + x;
            double engery = 0;
            if (isVertical) {
                engery = energy(x, n - 1);
            } else {
                engery = energy(n - 1, x);
            }
            DirectedEdge edge = new DirectedEdge(nextNodeId , m*n + 1, engery);
            graph.addEdge(edge);
        }
        //System.out.println(graph);
        DijkstraSP sp = new DijkstraSP(graph, m*n);
        Iterable<DirectedEdge> path = sp.pathTo(m*n + 1);
        //System.out.println(path);
        Iterator<DirectedEdge> iter = path.iterator();
        
        int [] result = new int[n];
        int i = 0;
        while (iter.hasNext()) {
            DirectedEdge edge = iter.next();
            System.out.println(edge);
            if (i < n) {
                result[i] = edge.to() % m;
            } 
            i++;
        }
        //result[0] = result[0] - 2;
        //result[n - 1] = result[n - 1] - 2;
        return result;
    }
       
   public Picture picture()                       // current picture
   {
       return picture;
   }
   
   public     int width()                         // width of current picture
   {
       return picture.width();
   }
   
   public     int height()                        // height of current picture
   {
       return picture.height();
   }
   
   public  double energy(int x, int y)  // energy of pixel at column x and row y
   {
       if (x < 0 || x > picture.width() -1 || y < 0 || y > picture.height() - 1)
           throw new java.lang.IndexOutOfBoundsException();
       if (x == 0 || x == picture.width() -1 || y == 0 || y == picture.height() - 1)
           return 195075;
       Color rightColor = picture.get(x + 1, y);
       Color leftColor = picture.get(x - 1, y);
       double rx = rightColor.getRed() - leftColor.getRed();
       double gx = rightColor.getGreen() - leftColor.getGreen();
       double bx = rightColor.getBlue() - leftColor.getBlue();
       double deltaX2 = rx*rx + gx*gx + bx*bx;
       
       Color downColor = picture.get(x, y + 1);
       Color upColor = picture.get(x, y - 1);
       double ry = downColor.getRed() - upColor.getRed();
       double gy = downColor.getGreen() - upColor.getGreen();
       double by = downColor.getBlue() - upColor.getBlue();
       double deltaY2 = ry*ry + gy*gy + by*by;
       
       return deltaX2 + deltaY2;
   }

   public int[] findHorizontalSeam() // sequence of indices for horizontal seam
   {
       return findSeam(false);
   }
   public int[] findVerticalSeam()     // sequence of indices for vertical seam
   {
       return findSeam(true);
   }
   public void removeHorizontalSeam(int[] a)   // remove horizontal seam from picture
   {
       if (a.length != picture.width()) {
           throw new java.lang.IllegalArgumentException();
       }
       
       for (int i = 1; i < a.length; i++) {
           if (Math.abs(a[i] - a[i - 1]) > 1) {
               throw new java.lang.IllegalArgumentException();               
           }
       }
       
       if (picture.height() == 0) {
           throw new java.lang.IllegalArgumentException();
       }
       
       Picture pict = new Picture(picture.width(), picture.height() - 1);
       for (int x = 0; x < picture.width(); x++) {
           int removed = a[x];
           for (int y = 0; y < picture.height() - 1; y++) {
               if (y < removed) {
                   pict.set(x, y, picture.get(x, y));
               } else {
                   pict.set(x, y, picture.get(x, y + 1));
               }
           }
       }
       this.picture = pict;
   }
   
   public void removeVerticalSeam(int[] a)     // remove vertical seam from picture
   {
       if (a.length != picture.height()) {
           throw new java.lang.IllegalArgumentException();
       }
       
       for (int i = 1; i < a.length; i++) {
           if (Math.abs(a[i] - a[i - 1]) > 1) {
               throw new java.lang.IllegalArgumentException();               
           }
       }
       
       if (picture.width() == 0) {
           throw new java.lang.IllegalArgumentException();
       }
       
       Picture pict = new Picture(picture.width() - 1, picture.height());
       for (int y = 0; y < picture.height(); y++) {
           int removed = a[y];
           for (int x = 0; x < picture.width() - 1; x++) {
               if (x < removed) {
                   pict.set(x, y, picture.get(x, y));
               } else {
                   pict.set(x, y, picture.get(x + 1, y));
               }
           }
       }
       this.picture = pict;
   }
   
    public static void main(String[] args) {
        Picture picture = new Picture(6, 5);
        /*picture.set(0, 0, new Color( 97, 82,107));
        picture.set(1, 0, new Color(220,172,141));
        picture.set(2, 0, new Color(243, 71,205));
        picture.set(3, 0, new Color(129,173,222));
        picture.set(4, 0, new Color(225, 40,209));
        picture.set(5, 0, new Color( 66,109,219)); 
        picture.set(0, 1, new Color(181, 78, 68));
        picture.set(1, 1, new Color( 15, 28,216));
        picture.set(2, 1, new Color(245,150,150));
        picture.set(3, 1, new Color(177,100,167));
        picture.set(4, 1, new Color(205,205,177));
        picture.set(5, 1, new Color(147, 58, 99)); 
        picture.set(0, 2, new Color(196,224, 21));
        picture.set(1, 2, new Color(166,217,190));
        picture.set(2, 2, new Color(128,120,162));
        picture.set(3, 2, new Color(104, 59,110));
        picture.set(4, 2, new Color( 49,148,137));
        picture.set(5, 2, new Color(192,101, 89)); 
        picture.set(0, 3, new Color( 83,143,103));
        picture.set(1, 3, new Color(110, 79,247));
        picture.set(2, 3, new Color(106, 71,174));
        picture.set(3, 3, new Color( 92,240,205));
        picture.set(4, 3, new Color(129, 56,146));
        picture.set(5, 3, new Color(121,111,147)); 
        picture.set(0, 4, new Color( 82,157,137));
        picture.set(1, 4, new Color( 92,110,129));
        picture.set(2, 4, new Color(183,107, 80));
        picture.set(3, 4, new Color( 89, 24,217));
        picture.set(4, 4, new Color(207, 69, 32));
        picture.set(5, 4, new Color(156,112, 31)); */        
        SeamCarver s = new SeamCarver(picture);
        /*
        for (int y = 0; y < s.height(); y++) {
            String str = "";
            for (int x = 0; x < s.width(); x++)
                str = str + s.energy(x, y) + ", ";
            System.out.println(str);
        }
        */
        int [] vSeam = s.findVerticalSeam();
        for (int i = 0; i < vSeam.length; i++)
            System.out.println(vSeam[i]);
    }
}

Algorithms, Part II Assignment 1

$
0
0

Programming Assignment 1: WordNet

WordNet is a semantic lexicon for the English language that is used extensively by computational linguists and cognitive scientists; for example, it was a key component in IBM’s Watson. WordNet groups words into sets of synonyms called synsets and describes semantic relationships between them. One such relationship is the is-a relationship, which connects a hyponym (more specific synset) to a hypernym (more general synset). For example, a plant organ is a hypernym of carrot and plant organ is a hypernym of plant root.

The WordNet digraph. Your first task is to build the wordnet digraph: each vertex v is an integer that represents a synset, and each directed edge v→w represents that w is a hypernym of v. The wordnet digraph is arooted DAG: it is acylic and has one vertex that is an ancestor of every other vertex. However, it is not necessarily a tree because a synset can have more than one hypernym. A small subgraph of the wordnet digraph is illustrated below.

 

The WordNet input file formats. We now describe the two data files that you will use to create the wordnet digraph. The files are in CSV format: each line contains a sequence of fields, separated by commas.

    • List of noun synsets. The file synsets.txt lists all the (noun) synsets in WordNet. The first field is the synset id (an integer), the second field is the synonym set (or synset), and the third field is its dictionary definition (or gloss). For example, the line 
      36,AND_circuit AND_gate,a circuit in a computer that fires only when all of its inputs fire

      means that the synset { AND_circuitAND_gate } has an id number of 36 and it’s gloss is a circuit in a computer that fires only when all of its inputs fire. The individual nouns that comprise a synset are separated by spaces (and a synset element is not permitted to contain a space). The S synset ids are numbered 0 through S − 1; the id numbers will appear consecutively in the synset file.

 

  • List of hypernyms. The file hypernyms.txt contains the hypernym relationships: The first field is a synset id; subsequent fields are the id numbers of the synset’s hypernyms. For example, the following line 
    164,21012,56099

    means that the the synset 164 ("Actifed") has two hypernyms: 21012 ("antihistamine") and 56099 ("nasal_decongestant"), representing that Actifed is both an antihistamine and a nasal decongestant. The synsets are obtained from the corresponding lines in the file synsets.txt.

     

    164,Actifed,trade name for a drug containing an antihistamine and a decongestant...
    21012,antihistamine,a medicine used to treat allergies...
    56099,nasal_decongestant,a decongestant that provides temporary relief of nasal...

WordNet data type. Implement an immutable data type WordNet with the following API:

// constructor takes the name of the two input files
public WordNet(String synsets, String hypernyms)

// the set of nouns (no duplicates), returned as an Iterable
public Iterable<String> nouns()

// is the word a WordNet noun?
public boolean isNoun(String word)

// distance between nounA and nounB (defined below)
public int distance(String nounA, String nounB)

// a synset (second field of synsets.txt) that is the common ancestor of nounA and nounB
// in a shortest ancestral path (defined below)
public String sap(String nounA, String nounB)

// for unit testing of this class
public static void main(String[] args)

The constructor should throw a java.lang.IllegalArgumentException if the input does not correspond to a rooted DAG. The distance() and sap() methods should throw ajava.lang.IllegalArgumentException unless both of the noun arguments are WordNet nouns.

Your data type should use space linear in the input size (size of synsets and hypernyms files). The constructor should take time linearithmic (or better) in the input size. The method isNoun() should run in time logarithmic (or better) in the number of nouns. The methods distance() and sap() should run in time linear in the size of the WordNet digraph.

Shortest ancestral path. An ancestral path between two vertices v and w in a digraph is a directed path from v to a common ancestor x, together with a directed path from w to the same ancestor x. A shortest ancestral path is an ancestral path of minimum total length. For example, in the digraph at left (digraph1.txt), the shortest ancestral path between 3 and 11 has length 4 (with common ancestor 1). In the digraph at right (digraph2.txt), one ancestral path between 1 and 5 has length 4 (with common ancestor 5), but the shortest ancestral path has length 2 (with common ancestor 0).

SAP data type. Implement an immutable data type SAP with the following API:

// constructor takes a digraph (not necessarily a DAG)
public SAP(Digraph G)

// length of shortest ancestral path between v and w; -1 if no such path
public int length(int v, int w)

// a common ancestor of v and w that participates in a shortest ancestral path; -1 if no such path
public int ancestor(int v, int w)

// length of shortest ancestral path between any vertex in v and any vertex in w; -1 if no such path
public int length(Iterable<Integer> v, Iterable<Integer> w)

// a common ancestor that participates in shortest ancestral path; -1 if no such path
public int ancestor(Iterable<Integer> v, Iterable<Integer> w)

// for unit testing of this class (such as the one below)
public static void main(String[] args)

All methods should throw a java.lang.IndexOutOfBoundsException if one (or more) of the input arguments is not between 0 and G.V() - 1. You may assume that the iterable arguments contain at least one integer. All methods (and the constructor) should take time at most proportional to E + V in the worst case, where E and V are the number of edges and vertices in the digraph, respectively. Your data type should use space proportional to E + V.

Test client. The following test client takes the name of a digraph input file as as a command-line argument, constructs the digraph, reads in vertex pairs from standard input, and prints out the length of the shortest ancestral path between the two vertices and a common ancestor that participates in that path:

public static void main(String[] args) {
    In in = new In(args[0]);
    Digraph G = new Digraph(in);
    SAP sap = new SAP(G);
    while (!StdIn.isEmpty()) {
        int v = StdIn.readInt();
        int w = StdIn.readInt();
        int length   = sap.length(v, w);
        int ancestor = sap.ancestor(v, w);
        StdOut.printf("length = %d, ancestor = %d\n", length, ancestor);
    }
}

Here is a sample execution:

% more digraph1.txt             % java SAP digraph1.txt
13                              3 11
11                              length = 4, ancestor = 1
 7  3                            
 8  3                           9 12
 3  1                           length = 3, ancestor = 5
 4  1
 5  1                           7 2
 9  5                           length = 4, ancestor = 0
10  5
11 10                           1 6
12 10                           length = -1, ancestor = -1
 1  0
 2  0

Measuring the semantic relatedness of two nouns. Semantic relatedness refers to the degree to which two concepts are related. Measuring semantic relatedness is a challenging problem. For example, most of us agree that George Bush and John Kennedy (two U.S. presidents) are more related than are George Bush and chimpanzee (two primates). However, not most of us agree that George Bush and Eric Arthur Blair are related concepts. But if one is aware that George Bush and Eric Arthur Blair (aka George Orwell) are both communicators, then it becomes clear that the two concepts might be related.

We define the semantic relatedness of two wordnet nouns A and B as follows:

  • distance(A, B) = distance is the minimum length of any ancestral path between any synset v of A and any synset w of B.

This is the notion of distance that you will use to implement the distance() and sap() methods in the WordNet data type.

Outcast detection. Given a list of wordnet nouns A1A2, …, An, which noun is the least related to the others? To identify an outcast, compute the sum of the distances between each noun and every other one:

di   =   dist(AiA1)   +   dist(AiA2)   +   …   +   dist(AiAn)

and return a noun At for which dt is maximum.

Implement an immutable data type Outcast with the following API:

// constructor takes a WordNet object
public Outcast(WordNet wordnet)

// given an array of WordNet nouns, return an outcast
public String outcast(String[] nouns)

// for unit testing of this class (such as the one below)
public static void main(String[] args)

Assume that argument array to the outcast() method contains only valid wordnet nouns (and that it contains at least two such nouns).

The following test client takes from the command line the name of a synset file, the name of a hypernym file, followed by the names of outcast files, and prints out an outcast in each file:

public static void main(String[] args) {
    WordNet wordnet = new WordNet(args[0], args[1]);
    Outcast outcast = new Outcast(wordnet);
    for (int t = 2; t < args.length; t++) {
        String[] nouns = In.readStrings(args[t]);
        StdOut.println(args[t] + ": " + outcast.outcast(nouns));
    }
}

Here is a sample execution:

% more outcast5.txt
horse zebra cat bear table

% more outcast8.txt
water soda bed orange_juice milk apple_juice tea coffee

% more outcast11.txt
apple pear peach banana lime lemon blueberry strawberry mango watermelon potato

% java Outcast synsets.txt hypernyms.txt outcast5.txt outcast8.txt outcast11.txt
outcast5.txt: table
outcast8.txt: bed
outcast11.txt: potato

Analysis of running time (optional). Analyze the effectiveness of your approach to this problem by giving estimates of its time requirements.

 

  • Give the order of growth of the worst-case running time of the length() and ancestor() methods in SAP as a function of the number of vertices V and the number of edges E in the digraph. 
  • Give the order of growth of the best-case running time of the same methods.

Deliverables. Submit WordNet.javaSAP.java, and Outcast.java that implement the APIs described above. Also submit any other supporting files (excluding those in stdlib.jar and algs4.jar).

 


This assignment was created by Alina Ene and Kevin Wayne.

Copyright © 2006

import java.util.Iterator;


public class SAP {
    private static final int INFINITY = Integer.MAX_VALUE;
    
    private Digraph G;
    private int ancestor;
    private int length;
    private int currentId = -1;

    //private boolean[] marked1;  // marked[v] = is there an s->v path?
    //private int[] edgeTo1;      // edgeTo[v] = last edge on shortest s->v path
   // private int[] distTo1;      // distTo[v] = length of shortest s->v path    
   // private boolean[] marked2;  // marked[v] = is there an s->v path?
   // private int[] edgeTo2;      // edgeTo[v] = last edge on shortest s->v path
   // private int[] distTo2;      // distTo[v] = length of shortest s->v path    

    // constructor takes a digraph (not necessarily a DAG)
    public SAP(Digraph G) {
        this.G = new Digraph(G.V());
        for (int v = 0; v < G.V(); v++) {
            Iterable<Integer> adj = G.adj(v);
            Iterator<Integer> iter = adj.iterator();
            while (iter.hasNext()) {
                int w = iter.next();
                this.G.addEdge(v, w);
            }
        }
    }
    // BFS from single source
    private void bfs(int s1, int s2) {
        if (s1 == s2) {
            length = 0;
            ancestor = s1;
            return;
        }
        BreadthFirstDirectedPaths b1 = new BreadthFirstDirectedPaths(G, s1);
        BreadthFirstDirectedPaths b2 = new BreadthFirstDirectedPaths(G, s2);
        length = INFINITY;
        for (int i = 0; i < G.V(); i++) {
            if (b1.hasPathTo(i) && b2.hasPathTo(i)) {
                int dist = b1.distTo(i) + b2.distTo(i);
                if (length > dist) {
                    length = dist;
                    ancestor = i;
                }
            }
        }
        if (length == INFINITY) {
            length = -1;
            ancestor = -1;
        }
        return;
    }
    
 

    // length of shortest ancestral path between v and w; -1 if no such path
    public int length(int v, int w) {
        if (v < 0 || v > G.V() -1 || w < 0 || w > G.V() -1) {
           throw new java.lang.IndexOutOfBoundsException();
        } 
        int id = v*G.V() + w;
        if (id != currentId) {
            bfs(v, w);
            currentId = id;
        }
        return length;        
    }

    // a common ancestor of v and w that participates in a shortest 
    // ancestral path; -1 if no such path
    public int ancestor(int v, int w) {
        if (v < 0 || v > G.V() -1 || w < 0 || w > G.V() -1) {
           throw new java.lang.IndexOutOfBoundsException();
        }
        int id = v*G.V() + w;
        if (id != currentId) {
            bfs(v, w);
            currentId = id;
        }
        return ancestor;
    }

    private Stack<Integer> reversePath(Iterable<Integer> path) {
        Iterator<Integer> pathIter = path.iterator();
        Stack<Integer> result = new Stack<Integer>();    
        while (pathIter.hasNext()) {
            result.push(pathIter.next());            
        }        
        return result;
    }
    
    // length of shortest ancestral path between any vertex in v and 
    //any vertex in w; -1 if no such path
    public int length(Iterable<Integer> v, Iterable<Integer> w) {
        Stack<Integer> pathA = reversePath(v);
        Stack<Integer> pathB = reversePath(w);
        
        Iterator<Integer> pathAIter = pathA.iterator();
        Iterator<Integer> pathBIter = pathB.iterator();
        if (!pathAIter.hasNext() || !pathBIter.hasNext()) {
            return -1;
        }
        int a = pathAIter.next();
        int b = pathBIter.next();
        if (a != b) {
            return -1;
        } 
        
        //int ancestor = a;
        int sapLevel = 0;
        while (pathAIter.hasNext() && pathBIter.hasNext()) {
            a = pathAIter.next();
            b = pathBIter.next();
            if (a == b) {
               // ancestor = a;
                sapLevel++;
            } else {
                break;
            }
        }
        return pathA.size() + pathB.size() - 2*sapLevel;
    }

    // a common ancestor that participates in shortest ancestral 
    //path; -1 if no such path
    public int ancestor(Iterable<Integer> v, Iterable<Integer> w) {
        Stack<Integer> pathA = reversePath(v);
        Stack<Integer> pathB = reversePath(w);
        
        Iterator<Integer> pathAIter = pathA.iterator();
        Iterator<Integer> pathBIter = pathB.iterator();
        if (!pathAIter.hasNext() || !pathBIter.hasNext()) {
            return -1;
        }
        int a = pathAIter.next();
        int b = pathBIter.next();
        if (a != b) {
            return -1;
        } 
        
        int result = a;
        //int sapLevel = 0;
        while (pathAIter.hasNext() && pathBIter.hasNext()) {
            a = pathAIter.next();
            b = pathBIter.next();
            if (a == b) {
                result = a;
                //sapLevel ++;
            } else {
                break;
            }
        }
        return result;        
    }

    // for unit testing of this class (such as the one below)
    public static void main(String[] args) {
        In in = new In(args[0]);
        Digraph G = new Digraph(in);
        SAP sap = new SAP(G);
        while (!StdIn.isEmpty()) {
            int v = StdIn.readInt();
            int w = StdIn.readInt();
            int length   = sap.length(v, w);
            int ancestor = sap.ancestor(v, w);
            StdOut.printf("length = %d, ancestor = %d\n", length, ancestor);
        }
    }
}

import java.util.ArrayList;
import java.util.Iterator;

public class WordNet {
    private static final int INFINITY = Integer.MAX_VALUE;
    
    private Digraph graph;
    private LinearProbingHashST<String, Integer> nounsHashTable 
                = new LinearProbingHashST<String, Integer>();
    private ArrayList<String> arrayList = new ArrayList<String>();
    //private int rootId; 
    //private Stack<Integer> pathA;
    //private Stack<Integer> pathB;
    //private int sap; 
    //private int sapLevel;
    private int ancestor;
    private int length;       
    // constructor takes the name of the two input files
    public WordNet(String synsets, String hypernyms) {
        In synsetsIn = new In(new java.io.File(synsets));
        int size = 0;
        while (synsetsIn.hasNextLine()) {
            String line = synsetsIn.readLine();
            int index = line.indexOf(",");
            int id = Integer.parseInt(line.substring(0, index));
            line = line.substring(index + 1);
            index = line.indexOf(",");
            String [] nounlist = line.substring(0, index).split(" ");
            for (int i = 0; i < nounlist.length; i++) {
                nounsHashTable.put(nounlist[i], id);
            }
            arrayList.add(line.substring(0, index));
            size = size + 1;
        }
        graph = new Digraph(size);
        In hypernymsIn = new In(new java.io.File(hypernyms));
        while (hypernymsIn.hasNextLine()) {
            String line = hypernymsIn.readLine();
            String [] items = line.split(",");
            int endId = Integer.parseInt(items[0]);
            for (int i = 1; i < items.length; i++) {
                int beginId = Integer.parseInt(items[i]);
                graph.addEdge(endId, beginId);
            }
        }        
        DirectedCycle directedCycle = new DirectedCycle(graph);
        if (directedCycle.hasCycle()) {
            throw new java.lang.IllegalArgumentException();
        }
        boolean isRootFound = false;
        for (int i = 0; i < graph.V(); i++) {
            Iterable<Integer> bag = graph.adj(i);
            Iterator<Integer> bagIter = bag.iterator();
            int bagSize = 0;
            while (bagIter.hasNext()) {
                bagSize++;
                bagIter.next();
            }
            if (bagSize == 0) {
                if (!isRootFound) {
                    isRootFound = true;
                    //rootId = i;
                } else {
                    throw new java.lang.IllegalArgumentException();
                }
            }
        }
    }

    // returns all WordNet nouns
    public Iterable<String> nouns() {
        return nounsHashTable.keys();
    }

    // is the word a WordNet noun?
    public boolean isNoun(String word) {
        return nounsHashTable.contains(word);
    }
    //private int [] distTo;
    //private int [] distTo1;

    private Stack<Integer> reversePath(Iterable<Integer> path) {
        Iterator<Integer> pathIter = path.iterator();
        Stack<Integer> result = new Stack<Integer>();    
        while (pathIter.hasNext()) {
            result.push(pathIter.next());            
        }        
        return result;
    }
    
    private void bfs(String nounA, String nounB) {
        if (!nounsHashTable.contains(nounA) || !nounsHashTable.contains(nounB)) {
            throw new java.lang.IllegalArgumentException();
        }
        int indexA = nounsHashTable.get(nounA);
        int indexB = nounsHashTable.get(nounB);
        System.out.println(indexA);
        System.out.println(indexB);
        
        BreadthFirstDirectedPaths b1 = new BreadthFirstDirectedPaths(graph, indexA);
        BreadthFirstDirectedPaths b2 = new BreadthFirstDirectedPaths(graph, indexB);
        /*pathA = reversePath(bA.pathTo(rootId));
        pathB = reversePath(bB.pathTo(rootId));
        
        Iterator<Integer> pathAIter = pathA.iterator();
        Iterator<Integer> pathBIter = pathB.iterator();
        sap = rootId;
        sapLevel = 0;
        while (pathAIter.hasNext() && pathBIter.hasNext()) {
            int a = pathAIter.next();
            int b = pathBIter.next();
            if (a == b) {
                sap = a;
                sapLevel++;
            } else {
                break;
            }
        }*/
        
        length = INFINITY;
        for (int i = 0; i < graph.V(); i++) {
            if (b1.hasPathTo(i) && b2.hasPathTo(i)) {
                int dist = b1.distTo(i) + b2.distTo(i);
                if (length > dist) {
                    length = dist;
                    ancestor = i;
                }
            }
        }
        if (length == INFINITY) {
            length = -1;
            ancestor = -1;
        }
        return;
    }
    
    // distance between nounA and nounB (defined below)
    public int distance(String nounA, String nounB) {
        bfs(nounA, nounB);
        //return pathA.size() + pathB.size() - 2*sapLevel;
        return length;
    }

    // a synset (second field of synsets.txt) that is the 
    //common ancestor of nounA and nounB
    // in a shortest ancestral path (defined below)
    public String sap(String nounA, String nounB) {
        bfs(nounA, nounB);
       // return arrayList.get(sap); //arrayList.get(w);
        return arrayList.get(ancestor);
    }

    // for unit testing of this class
    public static void main(String[] args) {
        WordNet wordNet = new WordNet("synsets.txt", "hypernyms.txt");
        System.out.println(wordNet.distance("rebuilding", "book"));
    }
}


public class Outcast {
    private WordNet wordnet;
    // constructor takes a WordNet object
    public Outcast(WordNet wordnet) {
        this.wordnet = wordnet;
    }

    // given an array of WordNet nouns, return an outcast
    public String outcast(String[] nouns) {
        int [][] distances = new int[nouns.length][nouns.length];
        for (int i = 0; i < nouns.length; i++) {
            String noun1 = nouns[i];
            distances[i][i] = 0;
            for (int j = i + 1; j < nouns.length; j++) {
                String noun2 = nouns[j];
                int dist = wordnet.distance(noun1, noun2);
                distances[i][j] = dist;
                distances[j][i] = dist;
            }
        }
        int maxDist = -1;
        int maxId = -1;
        for (int i = 0; i < nouns.length; i++) {
            int totalDist = 0;
            for (int j = 0; j < nouns.length; j++) {
                totalDist = totalDist + distances[i][j];
            }
            if (totalDist > maxDist) {
                maxDist = totalDist;
                maxId = i;
            }
        }
        return nouns[maxId];
    }

    // for unit testing of this class (such as the one below)
    public static void main(String[] args) {
        WordNet wordnet = new WordNet(args[0], args[1]);
        Outcast outcast = new Outcast(wordnet);
        for (int t = 2; t < args.length; t++) {
            String[] nouns = In.readStrings(args[t]);
            StdOut.println(args[t] + ": " + outcast.outcast(nouns));
        }
    }
}


Viewing all 764 articles
Browse latest View live