CS503: First Lecture, Fall 2008

farrightSoftware and s/w Development

Aug 15, 2012 (4 years and 8 months ago)


CS503: Seventeenth Lecture, Fall 2008

Problem Solving

Michael Barnathan

Here’s what we’ll be learning:


How to go from problems to code.

Problem solving as an art.

Mastery of your environment.


of Computer Programming

Your degree ends with the phrase “of Science”, but problem solving is very
much an art.

Programming, therefore, is a bit of both art and science.


Few hard, fast rules.

Some rules are unwritten.

Lots of room for creativity.

Improvement primarily through practice.


Usually well

defined methods (including the “scientific method”).

Improvement through practice and acquisition of knowledge.

Because the rules are well
defined, knowing them helps.

Still lots of room for creativity.

You can often “bend the rules”.

What is Computer Programming?

Actually writing the code is a
very small part

of being a
successful programmer.

70% of it is figuring out how to break a problem down into
small, solvable, unambiguous pieces.

20% is knowing what your tools are and how to use them
(languages, IDEs, debuggers…)

The other 10% is finding and using existing solutions so you’re
not reinventing the wheel.

Knowing the language is a necessary condition to be a
programmer at all, however!

Put it this way: does being fluent in English automatically
make you a good writer?

Of course not. But could you be a writer without knowing a
language? No; the language is your medium.

Your Tools

What trips most beginning CS students up is not an inability to solve
problems. It’s an inability to master their development environments.

You should know how to use, for each platform you develop on, at least:

The language you’re coding in, obviously.

1 IDE.

2 widely available command
line editors (have the labs convinced you why this
is important yet?)

1 compiler.

1 debugger.

1 UML/modeling program (Visio,
, the Eclipse UML
, the
Netbeans UML
, …)


1 profiling tool (such as


these programs can help you fix
performance bottlenecks and memory leaks, among other problems).

1 testing suite, such as

1 versioning/source control system, such as CVS or SVN.

Don’t rely on an IDE
. It’s a useful tool, but may not always be available.

Learning New Languages.

Most programmers who understand one
language well can learn new languages very

Right now, you could probably learn C# within a few
weeks if you wished.

It may take you a bit longer to learn, say, Prolog, but
probably no more than a month.

This is not accidental: the languages are related
and express similar concepts.

So what I am aiming to teach is not Java, per se,
but programming in general.

And Tools

Tools are the same way. Their authors make them more usable by copying
metaphors from other tools.

For example,

is a near
universal “open” shortcut. You could use it

F5, F7, or F9 will usually run your program.

F10, shift+F10, and F11 are usually used to step through a program in a


is a universal command to break execution of a program.

(It’s also the shortcut for the “copy” command.

is cut and



can be used to undo in most programs,

to redo.

The shortcuts you learn in one place will often be used again in another.

Even across platforms.

This makes learning the tools far easier.

Line Editors

Since you are developing in Linux, you should make an
effort to learn how to use either vim or

Both are extremely powerful yet lightweight command
editors, but not the easiest to use.

I developed every assignment for this course in vim.

If you need something easier
use, try

Reasons to prefer these to IDEs:

IDEs are cumbersome: if the project is small, they can do more
harm than good.

IDEs aren’t always available: there’s no guarantee you’ll be
allowed to install

on a system.

IDEs are bulky and slow: they try to do everything, but this can
slow them down and consume a lot of memory.

The Tao

To become one with the program, you must clear
your mind of all distractions.

In other words, stop hunting for menu commands
and start writing code!

To achieve the highly creative state known as
“flow”, you need to be completely focused on
solving the problem and writing code. You’ll
never reach it if you’re struggling with the editor.

This is the state where you churn out thousands of
lines of high
quality code per hour, keep going all day,
and only realize you forgot to eat after stopping.


Java’s debugger is known as

It’s a command line debugger, but frontends exist (IDEs build them in).

When compiling a program for a debugger, pass the
g option to
. This
embeds symbols describing your program’s variables in the compiled class file.

Simple commands:

help (by far the most important)

run: Runs the currently loaded program.

stop: Sets a breakpoint. The debugger will interrupt execution to allow debugging when a
breakpoint is hit.

“stop at Test:24”: breaks at test.java, line 24.

“stop in
”: breaks when

is invoked.

print: prints out a variable or method’s value.

step: steps through the program line

cont: continues execution after a breakpoint is hit.

where: prints a stack trace.

up: goes one frame up the system stack. (pops)

down: goes one frame down the system stack if not already at the bottom. (pushes)

locals: lists all local variables in the current stack frame.

list: prints the source around the current location.

Version Control

Your own personal time machine.

Stores old versions of programs and lets you revert back to them at need.

Also great for collaboration or if you work on the same documents from
place to place.

Every time you make a revision, you can save, or “commit” it to a version
control repository.

You can later compare further changes to any old version you’ve ever
committed (“diff”) or revert your changes entirely by “updating” to an old

If you move to another system with an old copy, you can “update” it to the
newest committed revision as well.

You can also “check out” the latest update on a new system at any time.

The most popular systems are Subversion (SVN) and CVS. Using one will
make your task far easier.

Existing Solutions

You have other sorts of tools, too. These don’t help you code; they
help you







CPAN (for Perl) and other module repositories.

Many others…

Use these when you hit roadblocks: chances are that others have
hit them too, and their solutions can help you.

Also use them to find libraries; try not to waste time doing
something that has already been done.

Being able to quickly understand and use these libraries from their
documentation is an essential programming skill as well.

What’s the Connection?

What lets me take metaphors from one
language or UI and simply assume they will
work in others?

Why can some people use programs they had
never seen before, while others have difficulty
with tasks they haven’t memorized?


Intuitive Design

Good UIs are intuitive.

They place tasks where users expect to find them (e.g. “Open” is always under
the “File” menu because it’s the first place people will look).

They utilize the same sorts of shortcuts as other programs.

Commands are placed according to their function; common functionalities are

Frequently used commands should be easy to access.

Good languages are intuitive.

They do what you’d expect them to, and

what you’d expect them to.

Command names hint at their functionality.

Nothing is “magic”; commands don’t mean different things in different places.


are intuitive.

Variable and function names represent their functions.

There is a sense of overall structure to the program.

The pieces are split up in a self
contained way, like a puzzle fitting together.

It is clear what role each piece plays in solving the problem.

Nothing is done “by accident”

every piece of the program serves a purpose.

Problem Solving

An art: there are no strict rules.

There are some recurring patterns, though.

Takes both intelligence and creativity.

Most people don’t realize it at first, but computer science is a very creative field.

The algorithm design paradigms are problem solving strategies:

Divide and Conquer: break the problem down into smaller instances of itself, solve them, and
merge them back together.

Memoization: store solutions to smaller problems and look them up when needed.

The Greedy Approach: solve the problem by making the best short
term decision at each step.

Dynamic Programming: build the solution up from overlapping smaller solutions.

Also some others we didn’t discuss:

Hill Climbing: come up with an approximate solution, then gradually improve it.

Genetic Algorithms: generate many solutions, have them compete, and select the best ones.

Solutions are often easier to verify than to generate, so this can work well.

Visualization of the problem can help you solve it.

Flowcharts, UML, graphs, diagrams… sometimes the key is to just get an image of what the
solution must do into your head.

Intuition is important here too: go beyond the verbal description of the problem
and try to understand what the problem actually is.


Only once you understand the problem can you
begin working on a solution to it.

In programming, the solution usually involves an
“architecture”: some hierarchy of self
components which interact to generate a

Algorithms are recipes for solving problems, so
think of the architecture as a way of enabling you
to do complex things like “create a pizza crust”,
rather than having to list out each step involved
in creating a crust at once.

Problem: Make a Pizza

Questions to ask:

What is a pizza?


food with a crust on the bottom, topped with
cheese and tomato sauce.

What “high
level” ingredients will be required?




How can they interact to create a pizza?

The crust can be rolled thin, the sauce spread on top of
it, and the cheese added, in that order. The assembled
pizza is then baked in a pizza oven for 10 to 15 minutes.


What is involved in generating the crust, sauce,
and cheese?

Crust: flour, wheat, water, … must be mixed to
generate a dough.

Sauce: either created by mashing tomatoes or simply
bought ready
made (

Cheese: needs to be shredded before topping on a

Note that we don’t care about rolling the dough,
adding the sauce, or adding the cheese at this
level. We’ve dealt with that above.


Once we’ve drilled down to an elementary level, we are ready to construct a
solution from our architecture:

() {

//Gather low
level ingredients.

Tomato[] tomatoes = new Tomato[5];

Flour fl =


= new Mozzarella();

//Polymorphism. Mozzarella “ISA” Cheese.

Water w =

//Pour 4 ounces of water.


= Crust.mix(fl, w);

Sauce s =

Pizza p = new Pizza(
, s,

(p, 350, 15);

return p;


Now With a Program

Say you wanted to create a booking system for
an airline.

What components would your program need?

How would they interact?

What low
level operations might each component
need to perform?

What data must be stored by each?

I have problems.

This lesson was on problem solving and
problem decomposition, as well as mastery of
your development environment.

Specifically, it covered how to solve problems
using the programming techniques you have
been learning in this course and elsewhere.

The lesson:

Problem solving is often a matter of intuition, in
which both intelligence and creativity are brought
to bear.