]]>
package prefinal;
public class MyString {
private char[] charries;
public MyString(char[] src) {
charries = src;
}
/**
* Gets the index of first instance of the
* specified character. If character cannot
* be found, -1 is returned.
*/
public int indexOf(char c) {
for (int i = 0; i < charries.length; ++i) {
if (charries[i] == c) {
return i;
}
}
return -1;
}
public int lastIndexOf(char c) {
for (int i = charries.length - 1; i >= 0; --i) {
if (charries[i] == c) {
return i;
}
}
return -1;
}
public int length() {
return charries.length;
}
public char charAt(int i) {
return charries[i];
}
public boolean startsWith(MyString prefix) {
// This string isn't long enough to even contain prefix.
// Oh my goodness! Let's get outta here.
if (prefix.length() > length()) {
return false;
}
for (int i = 0; i < prefix.length(); ++i) {
if (prefix.charAt(i) != charAt(i)) {
return false;
}
}
return true;
}
public static void main(String[] args) {
MyString stuff = new MyString("The quick brown fox jumped over the lazy dog".toCharArray());
System.out.println(stuff.indexOf('T'));
System.out.println(stuff.indexOf('q'));
System.out.println(stuff.indexOf('z'));
System.out.println(stuff.indexOf('3'));
System.out.println(stuff.lastIndexOf('.'));
System.out.println(stuff.lastIndexOf('u'));
System.out.println(stuff.startsWith(new MyString("Bless you".toCharArray())));
System.out.println(stuff.startsWith(new MyString("".toCharArray())));
}
}
package prefinal;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
public class Ripple {
public static void main(String[] args) throws FileNotFoundException {
double[][] heights = new double[100][100];
for (int r = 0; r < heights.length; ++r) {
for (int c = 0; c < heights[r].length; ++c) {
int diffX = c - heights[r].length / 2;
int diffY = r - heights.length / 2;
double distance = Math.sqrt(diffX * diffX + diffY * diffY);
heights[r][c] = Math.sin(distance);
}
}
PrintWriter out = new PrintWriter("/home/user/Desktop/heights.txt");
for (int r = 0; r < heights.length; ++r) {
for (int c = 0; c < heights[r].length; ++c) {
out.print(heights[r][c] + " ");
}
out.println();
}
out.close();
}
}
#!/bin/sh mkdir -p dialup_friendlies for img in *.JPG; do convert $img -resize 300x300 dialup_friendlies/$img done
#!/bin/sh mailx -A uwec -H | grep '^ U' > /dev/null if [ $? -eq 0 ]; then echo "You have mail." fi
#!/usr/bin/env zsh for username in $(cat usernames.txt); do echo Sending mail to $username... mailx -A uwec -s "[CS 330] Lecture Spam" -r johnch@uwec.edu $username@uwec.edu < message.txt done
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public class WavIO {
/**
* The sampling frequency.
*/
public static final int SAMPLE_RATE = 22050;
/**
* Write the buffer containing audio samples to the specified file in WAV
* format.
*
* @param buffer Audio samples.
* @param path Path to destination WAV file.
*/
public static void write(short[] buffer, String path) {
try {
LEDataOutputStream out = new LEDataOutputStream(path);
out.writeBytes("RIFF"); // 0-3
out.writeInt(36 + buffer.length * 2); // 4-7
out.writeBytes("WAVE"); // 8-11
out.writeBytes("fmt "); // 12-15
out.writeInt(16); // chunk size, 16-19
out.writeShort((short) 1); // pcm, 20-21
out.writeShort((short) 1); // nchannels, 22-23
out.writeInt(SAMPLE_RATE); // 24-27
out.writeInt(SAMPLE_RATE * 2); // 28-31
out.writeShort((short) 2); // 32-33
out.writeShort((short) 16); // 34-35
out.writeBytes("data"); // 36-39
out.writeInt(buffer.length * 1 * 16 / 8); // 40-43
out.write(buffer);
out.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
/**
* A class for writing primitives to a file in little endian format.
*/
class LEDataOutputStream {
/** The underlying big endian file writer. */
private DataOutputStream out;
/** A collection of bytes used for an endian switcharoo. */
private byte[] bytes;
/** An endian switcher. */
private ByteBuffer buffer;
/**
* Create a new little endian file writer for the specified file.
*
* @param file
* Name of file to write.
*
* @throws FileNotFoundException
*/
public LEDataOutputStream(String file) throws FileNotFoundException {
out = new DataOutputStream(new FileOutputStream(file));
bytes = new byte[4];
buffer = ByteBuffer.wrap(bytes);
buffer.order(ByteOrder.LITTLE_ENDIAN);
}
/**
* Write the specified String as a series of bytes.
*
* @param s
* The String to write.
*
* @throws IOException
*/
public void writeBytes(String s) throws IOException {
out.writeBytes(s);
}
/**
* Write the specified int.
*
* @param value
* Value to write.
*
* @throws IOException
*/
public void writeInt(int value) throws IOException {
buffer.putInt(0, value);
out.write(bytes, 0, 4);
}
/**
* Writer the specified short.
*
* @param value
* Value to write.
*
* @throws IOException
*/
public void writeShort(short value) throws IOException {
buffer.putShort(0, value);
out.write(bytes, 0, 2);
}
/**
* Write the sequence of shorts. All values in the array are written in the
* order in which they appear in the array.
*
* @param shorts
* The sequence of values to write.
*
* @throws IOException
*/
public void write(short[] shorts) throws IOException {
for (int i = 0; i < shorts.length; ++i) {
writeShort(shorts[i]);
}
}
/**
* Close the file.
*
* @throws IOException
*/
public void close() throws IOException {
out.close();
}
}
package prefinal;
import java.util.Random;
public class Moosic {
public static void main(String[] args) {
Random generator = new Random();
short[] a = getNote(440.0, 2);
short[] c = getNote(523.25, 2);
short[] song = merge(a, c);
song = merge(song, song);
WavIO.write(song, "/home/user/Desktop/song.wav");
}
private static short[] merge(short[] a,
short[] b) {
short[] merged = new short[a.length + b.length];
System.arraycopy(a, 0, merged, 0, a.length);
System.arraycopy(b, 0, merged, a.length, b.length);
return merged;
}
private static short[] getNote(double frequency,
double nseconds) {
int nsamples = (int) (nseconds * WavIO.SAMPLE_RATE);
short[] samples = new short[nsamples];
for (int i = 0; i < samples.length; ++i) {
double t = i / (double) WavIO.SAMPLE_RATE;
samples[i] = (short) (Short.MAX_VALUE * Math.cos(frequency * t * 2 * Math.PI));
}
return samples;
}
}
lang(scheme).
lang(c).
static(c).
staticlang(X) :- lang(X), static(X).
/* Graph stuff */
edge(a, b).
edge(b, e).
edge(b, d).
edge(c, d).
path(X, Y) :- edge(X, Y).
path(X, Y) :- edge(X, Z), path(Z, Y).
/* Is even or odd? */
isodd(0) :- fail.
isodd(1).
isodd(N) :- N > 1, M is N - 1, iseven(M).
iseven(0).
iseven(1) :- fail.
iseven(N) :- N > 0, M is N - 1, isodd(M).
/* Member? */
/* I is only element in list. */
ismember(I, [I]).
/* I is first element in list. */
ismember(I, [I|_]).
/* I is in the tail. */
ismember(I, [_|T]) :- ismember(I, T).
/* Sorted? */
sorted([]).
sorted([_]).
sorted([A,B|T]) :- A =< B, write(A), write(' is <= '), write(B), nl, sorted([B|T]).
We want to write a little geography quizzer. The player is dropped into a country and must identify its capital and neighbors before she can leave. To win (an education), the player must clear all countries. The author/level designer can draft up “maps” in a custom world description language. Perhaps it looks something like:
USA HAS CAPITAL "Washington, DC"
Mexico HAS CAPITAL "Mexico City"
Canada HAS CAPITAL "Ottawa"
Mexico BORDERS USA
Canada BORDERS USA
We need to parse this file first thing inside our interpreter. Suppose our grammar is in World.g, then our interpreter starts off with:
// Lex and parse world file.
WorldLexer::InputStreamType world_in((ANTLR_UINT8 *) argv[1],
ANTLR_ENC_8BIT);
WorldLexer world_lexer(&world_in);
WorldParser::TokenStreamType world_tokens(ANTLR_SIZE_HINT,
world_lexer.get_tokSource());
WorldParser parser(&world_tokens);
parser.SetCountries(&countries);
parser.file();
It’s going to the task of the world parser to set up our countries list. Since we’ll need access to these country objects in a variety of places, let’s declare and define the country object and its helper in their own files:
#ifndef COUNTRY_H
#define COUNTRY_H
#include <string>
#include <map>
using std::string;
using std::map;
using std::pair;
/**
We need a forward declaration of Country because Neigbor and Country are
codependent. Neither one can be first 'cuz they need each other.
*/
class Country;
class Neighbor;
/**
C++ templated types are too much.
*/
typedef map<string, Country *> n2c_t;
typedef map<string, Neighbor> hood_t;
/**
Before the player can leave a country, she must identify all neigbors.
This struct encapsulates a neighbor and its identification status.
*/
struct Neighbor {
Neighbor(Country *c)
: neighbor(c),
is_identified(false) {
}
Country *neighbor;
bool is_identified;
};
/**
A country is a name, capital, and a set of neighbors. To leave a
country, its capital and numbers must be identified.
*/
class Country {
public:
Country(const std::string& name,
const std::string& capital);
const std::string& GetName() const;
const std::string& GetCapital() const;
hood_t& GetNeighbors();
const hood_t& GetNeighbors() const;
void AddNeighbor(Country *country);
void IsCapitalIdentified(bool is_guessed);
bool IsCapitalIdentified() const;
bool IsCleared() const;
int GetIdentifiedNeighborsCount() const;
private:
string name;
string capital;
hood_t neighbors;
bool is_capital_guessed;
};
std::ostream& operator<<(std::ostream& out, const Country *country);
#endif
The implementation:
#include "Country.h"
#include <iostream>
/* ------------------------------------------------------------------------- */
Country::Country(const std::string& name,
const std::string& capital)
: name(name),
capital(capital),
neighbors(),
is_capital_guessed(false) {
}
/* ------------------------------------------------------------------------- */
const std::string& Country::GetName() const {
return name;
}
/* ------------------------------------------------------------------------- */
const std::string& Country::GetCapital() const {
return capital;
}
/* ------------------------------------------------------------------------- */
hood_t& Country::GetNeighbors() {
return neighbors;
}
/* ------------------------------------------------------------------------- */
const hood_t& Country::GetNeighbors() const {
return neighbors;
}
/* ------------------------------------------------------------------------- */
std::ostream& operator<<(std::ostream& out, const Country *country) {
std::cout << country->GetName() << std::endl;
std::cout << country->GetCapital() << std::endl;
hood_t::const_iterator neighbor;
for (neighbor = country->GetNeighbors().begin();
neighbor != country->GetNeighbors().end();
++neighbor) {
std::cout << "Borders " << neighbor->first << std::endl;
}
return out;
}
/* ------------------------------------------------------------------------- */
void Country::AddNeighbor(Country *country) {
neighbors.insert(pair<string, Neighbor>(country->GetName(),
Neighbor(country)));
}
/* ------------------------------------------------------------------------- */
void Country::IsCapitalIdentified(bool is_guessed) {
is_capital_guessed = is_guessed;
}
/* ------------------------------------------------------------------------- */
bool Country::IsCapitalIdentified() const {
return is_capital_guessed;
}
/* ------------------------------------------------------------------------- */
bool Country::IsCleared() const {
return IsCapitalIdentified() &&
GetIdentifiedNeighborsCount() == neighbors.size();
}
/* ------------------------------------------------------------------------- */
int Country::GetIdentifiedNeighborsCount() const {
int nidentified = 0;
for (hood_t::const_iterator i = neighbors.begin();
i != neighbors.end();
++i) {
if (i->second.is_identified) {
++nidentified;
}
}
return nidentified;
}
/* ------------------------------------------------------------------------- */
Okay, now let’s think about the grammar. First, the boilerplate:
grammar World;
options {
language = Cpp;
}
@parser::includes {
#include <iostream>
#include "WorldLexer.hpp"
#include "Country.h"
}
@lexer::traits {
class WorldLexer;
class WorldParser;
typedef antlr3::Traits<WorldLexer, WorldParser> WorldLexerTraits;
typedef WorldLexerTraits WorldParserTraits;
}
@context {
private:
n2c_t *countries;
public:
void SetCountries(n2c_t *countries);
}
@members {
void WorldParser::SetCountries(n2c_t *countries) {
this->countries = countries;
}
}
Now the world parser has a pointer to the names-countries map. This parser’s job is to populate it as it sees countries.
Let’s think about our starting production. We’re parsing a file which has commands on each line. We can match that with:
file
: line* EOF
;
Each line is either a declaration command or a border command:
line : country=ID HAS CAPITAL capital=STRING | country1=ID BORDERS country2=ID ;
Let’s postpone for one moment handling the actions to take on parsing these commands. Let’s round out our terminals:
HAS : 'HAS';
CAPITAL : 'CAPITAL';
BORDERS : 'BORDERS';
ID
: ('a'..'z' | 'A' .. 'Z')+
;
STRING
: '"' (options {greedy=false;}: .)* '"'
;
WHITESPACE
: ('\r'|'\n'|'\t'|' ')+ {skip();}
;
Note how I match quote-enclosed strings. I have to use the non-greedy option just like in Perl. Otherwise I’ll zoom into the very last string in the file.
Okay, I’m at a point where I should try compiling something. A makefile is indespensable:
ANTLR_DIR = /home/user/330/antlrcpp
ANTLR = java -jar $(ANTLR_DIR)/antlr-3.4-with-cpp.jar
WORLD_SRC = WorldLexer.cpp WorldParser.cpp
WORLD_INCLUDE = WorldLexer.hpp WorldParser.hpp
GOLLYGEO_SRC = GollygeoLexer.cpp GollygeoParser.cpp
GOLLYGEO_INCLUDE = GollygeoLexer.hpp GollygeoParser.hpp
GRAMMARS_SRC = $(WORLD_SRC) #$(GOLLYGEO_SRC)
interpreter: interpreter.cpp Country.cpp $(GRAMMARS_SRC) #GeoPlayer.h
g++ -I$(ANTLR_DIR)/include -o interpreter -Wall interpreter.cpp Country.cpp $(GRAMMARS_SRC)
$(WORLD_SRC) $(WORLD_INCLUDE): World.g
$(ANTLR) World.g
$(GOLLYGEO_SRC) $(GOLLYGEO_INCLUDE): Gollygeo.g
$(ANTLR) Gollygeo.g
Let’s verify that parser parses. Does it? I hope so.
Now we want to actually define the actions to take on parsing. Let’s set up our test first. In our interpreter, we add:
n2c_t countries;
...
n2c_t::iterator country;
for (country = countries.begin(); country != countries.end(); ++country) {
std::cout << "country->second: " << country->second << std::endl;
}
Now let’s flesh out the rules. On seeing a country declaration, we simply insert its record into our name-countries map:
{
// Turn ID tokens into C++ strings.
string country_name = string($country.text);
string capital_name = string($capital.text);
// Make sure author didn't found a country twice.
n2c_t::iterator match = countries->find(country_name);
if (match != countries->end()) {
std::cerr << "Country " << country_name << " declared twice." << std::endl;
} else {
Country *new_country = new Country(country_name, capital_name);
countries->insert(pair<string, Country *>(country_name, new_country));
}
}
The text behind a terminal is in ANTLR string form. We convert to a std::string.
Let’s test. Does it work? I hope so.
Now, let’s add neighbors:
{
// Turn ID tokens into C++ strings.
string country1_name = string($country1.text);
string country2_name = string($country2.text);
// Assert that countries have already been declared.
n2c_t::iterator match1 = countries->find(country1_name);
n2c_t::iterator match2 = countries->find(country2_name);
if (match1 == countries->end()) {
std::cerr << "Country " << country1_name << " not declared." << std::endl;
} else if (match2 == countries->end()) {
std::cerr << "Country " << country2_name << " not declared." << std::endl;
}
// Mark border-relationships.
else {
match1->second->AddNeighbor(match2->second);
match2->second->AddNeighbor(match1->second);
}
}
Let’s test.
Okay, now we want the player to be able to interact. We’re going to drop the player in the starting country and let her enter in commands to identify capitals and neighbors. Let’s augment our interpreter:
GeoPlayer player;
player.current = countries.find("USA")->second;
// Lex and parse user commands, one line at a time.
std::string command;
std::cout << "> ";
while (getline(std::cin, command)) {
GollygeoLexer::InputStreamType gollygeo_in((ANTLR_UINT8 *) command.c_str(), ANTLR_ENC_8BIT, command.length(), (ANTLR_UINT8 *) "command");
GollygeoLexer gollygeo_lexer(&gollygeo_in);
GollygeoParser::TokenStreamType gollygeo_tokens(ANTLR_SIZE_HINT, gollygeo_lexer.get_tokSource());
GollygeoParser gollygeo_parser(&gollygeo_tokens);
gollygeo_parser.SetCountries(&countries, &player);
gollygeo_parser.line();
std::cout << "> ";
}
std::cout << std::endl;
This parser will need the countries to do semantic checking (is that really a country? is that really its capital? etc.). It’ll also need a player that it can move around to different countries once the current country is cleared. Let’s add that simple player class:
#ifndef GEOPLAYER_H
#define GEOPLAYER_H
#include "Country.h"
struct GeoPlayer {
Country *current;
};
#endif
Okay, let’s get the boilerplate for our grammar:
grammar Gollygeo;
options {
language = Cpp;
}
@parser::includes {
#include <iostream>
#include "GollygeoLexer.hpp"
#include "Country.h"
#include "GeoPlayer.h"
}
@lexer::traits {
class GollygeoLexer;
class GollygeoParser;
typedef antlr3::Traits<GollygeoLexer, GollygeoParser> GollygeoLexerTraits;
typedef GollygeoLexerTraits GollygeoParserTraits;
}
@context {
private:
n2c_t *countries;
GeoPlayer *player;
public:
void SetCountries(n2c_t *countries,
GeoPlayer *player);
}
@members {
void GollygeoParser::SetCountries(n2c_t *countries,
GeoPlayer *player) {
this->countries = countries;
this->player = player;
}
}
And let’s add the terminals:
LOOK: ('?'|'l');
GO: 'go';
TO: 'to';
CAPITAL: 'capital';
BORDERS: 'borders';
ID
: ('a'..'z' | 'A' .. 'Z')+
;
STRING
: '"' (options {greedy=false;}: .)* '"'
;
WHITESPACE
: ('\r'|'\n'|'\t'|' ')+ {skip();}
;
A lexer-parser will be generated for each command-line entered, so we’re only trying to parse a single command. Let’s let the user look around, identify the capital of the current country, identify neighbors, and go to neighbors once the capital and all neighbors have been identified:
line : LOOK EOF | CAPITAL STRING EOF | GO TO ID EOF | BORDERS ID EOF ;[/precode]
LOOK posts a short status message:
{
std::cout << "You are in " << player->current->GetName() << "." << std::endl;
std::cout << "You've " << (player->current->IsCapitalIdentified() ? "" : "not ") << "identified the capital." << std::endl;
std::cout << "You've identified " << player->current->GetIdentifiedNeighborsCount() << " of " << player->current->GetNeighbors().size() << " neighbors." << std::endl;
}
CAPITAL checks that the current country does indeed have this capital:
{
string guess = string($STRING.text);
if (guess == player->current->GetCapital()) {
std::cout << "Right! " << guess << " is the capital of " << player->current->GetName() << "." << std::endl;
player->current->IsCapitalIdentified(true);
} else {
std::cout << "Wrong!" << std::endl;
}
}
NEIGHBOR checks that the current country does indeed border this other country:
{
string country_name = string($ID.text);
hood_t::iterator match = player->current->GetNeighbors().find(country_name);
if (match != player->current->GetNeighbors().end()) {
match->second.is_identified = true;
std::cout << "Right on! " << country_name << " does border " << player->current->GetName() << "." << std::endl;
std::cout << "You've identified " << player->current->GetIdentifiedNeighborsCount() << " of " << player->current->GetNeighbors().size() << " neighbors." << std::endl;
} else {
std::cout << "No country named " << country_name << " shares a border with " << player->current->GetName() << "." << std::endl;
}
}
And GO TO moves the player when the current country is cleared:
{
if (!player->current->IsCleared()) {
std::cout << "You're business here is not done." << std::endl;
} else {
string country_name = string($ID.text);
hood_t::const_iterator match = player->current->GetNeighbors().find(country_name);
if (match != player->current->GetNeighbors().end()) {
player->current = match->second.neighbor;
std::cout << "You are now in " << player->current->GetName() << "." << std::endl;
} else {
std::cout << "No country named " << country_name << " shares a border with " << player->current->GetName() << "." << std::endl;
}
}
}
Whew. Did it work?
]]>You have:
How do you draw the polygon?
package prefinal;
public class Point {
private int x;
private int y;
public Point(int x,
int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
package prefinal;
import java.awt.Graphics;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ZaboomafuCanvas extends JPanel {
private GrowablePointArray points;
public ZaboomafuCanvas(GrowablePointArray points) {
this.points = points;
}
protected void paintComponent(Graphics g) {
for (int i = 0; i < points.size() - 1; ++i) {
drawLineBetween(g, points.get(i), points.get(i + 1));
}
drawLineBetween(g, points.get(0), points.get(points.size() - 1));
}
private void drawLineBetween(Graphics g,
Point a,
Point b) {
g.drawLine(a.getX(), a.getY(), b.getX(), b.getY());
}
public static void main(String[] args) throws FileNotFoundException {
JFrame frame = new JFrame();
// Point[] points = {
// new Point(50, 100),
// new Point(100, 100),
// new Point(75, 0),
// };
Scanner in = new Scanner(new File("/home/user/rectangle.txt"));
// int nPoints = 0;
// Point[] points = new Point[
GrowablePointArray points = new GrowablePointArray();
while (in.hasNextInt()) {
int x = in.nextInt();
int y = in.nextInt();
Point point = new Point(x, y);
// points[nPoints] = point;
// ++nPoints;
points.add(point);
}
frame.add(new ZaboomafuCanvas(points));
frame.setSize(200, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
]]>