Wednesday, August 3, 2011

Brownies

My friend Josie found this really simple and good brownie recipe, and I made them again recently so I am posting it here now.
Josie and I made brownies a while ago, and the recipe she had was very quick and easy, the next day the page of the book she wrote it on got soaked and she couldn't read it any more, so here is a copy transcribed from pictures.
Vegan Brownies
2 cups unbleached all purpose flour
2 cups white sugar (or other)
3/4 cup cocoa
1 teaspoon baking powder
1 teaspoon salt
1 cup water
1 cup vegetable oil
1 teaspoon vanilla extract
1. Preheat oven to 350 f
2. Stir together flour, sugar, cocoa powder, and salt. Pour in water, oil, and vanilla, blend well, spread evenly in a 9 x 13 inch baking pan.
3. Bake for 25 to 30 minutes in preheated oven, until top is no longer shiny, let cool about 10 minutes before cutting into squares.

YAY
BROWNIES!

Saturday, March 19, 2011

video to mp3

I had a desire to take a video file and extract the audio track into an mp3 file, so I ended up using a variant of the mp4 converter script to do the job.

#!/bin/bash
[ "$1" ] || {
  echo use: $0 file...
  exit 0
}

for file in "$@"; do
  ffmpeg -i "$file" -acodec libmp3lame -aq 100 "$file.mp3"
done

This script should work on most audio or video formats and makes variable bit rate high quality mp3 files.

Wednesday, March 2, 2011

mount on plug of external disk

For the home server we got an external USB powered hard disk for the public file share. Because this disk may not be present when the computer is started up, and may change device name since it is USB attached, I desired a way to mount that specific hard disk when it was plugged in.

The answer was a fairly long but simple udev rule, and a script to do the mounting.

/etc/udev/rules.d/storage.rules
ATTRS{idVendor}=="0bc2", ATTRS{idProduct}=="5031", ATTRS{serial}=="NA0B3DKV", ENV{DEVTYPE}=="partition", ACTION=="add", RUN+="/usr/local/sbin/mount-storage"

/usr/local/sbin/mount-storage
#!/bin/sh
mount -t vfat -o uid=nobody,gid=nogroup,dmask=000,fmask=111 \
 "$DEVNAME" /mnt/store

I found how to write the rule after referring to Writing udev rules and an example of a rule that matches the type of device.

It is still required to unmount the disk before unplugging it, as is the case with any operating system at the moment.

Monday, February 28, 2011

pancake syrup

When I am making pancakes, sometimes I like to have brown sugar syrup with them, it is also much cheaper to make pancake syrup from scratch than to buy it from the grocery store.

mix 1 cup brown sugar
and 2 cups water

boil for 25 minutes.

add vanilla.

That's all there is to that one.

Monday, February 21, 2011

console input in java

I wrote up a sample of nice and clean console input with validation, and repeated prompting on invalid inputs.

package org.yi.happy.console;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class DemoInput {
    /**
     * A demo of prompting for and reading validated data from standard input.
     */
    public static void main(String[] args) {
        try {
            /*
             * get a usable line reader.
             */
            BufferedReader in = new BufferedReader(new InputStreamReader(
                    System.in));

            /*
             * the result of the read loop
             */
            String word = null;
            /*
             * keep going until we get what we want
             */
            while (true) {
                /*
                 * ask the question
                 */
                System.out.print("enter a word: ");
                /*
                 * get the answer
                 */
                String line = in.readLine();
                /*
                 * is the answer what we want?
                 */
                if (line.matches("\\w+")) {
                    /*
                     * save the answer and done
                     */
                    word = line;
                    break;
                } else {
                    /*
                     * report a bad answer and repeat
                     */
                    System.out.println("that does not look like a word: "
                            + line);
                    continue;
                }
            }

            /*
             * the result of the read loop
             */
            double number = 0;
            /*
             * keep going until we get what we want
             */
            while (true) {
                /*
                 * ask the question
                 */
                System.out.print("enter a number: ");
                /*
                 * get the answer
                 */
                String line = in.readLine();
                /*
                 * parse the answer
                 */
                try {
                    number = Double.parseDouble(line);

                    /*
                     * range checks can go here (on failure do a continue, on
                     * accept do a break)
                     */

                    /*
                     * it was good, done
                     */
                    break;
                } catch (NumberFormatException e) {
                    /*
                     * it was not good, report the bad answer and repeat
                     */
                    System.out.println("that does not look like a number: "
                            + line);
                    continue;
                }
            }

            /*
             * if we get here we have two good answers.
             */

            /*
             * do something using the input
             */
            System.out.println("the word was " + word + " and the number was "
                    + number);

        } catch (IOException e) {
            /*
             * there was an error, so display it and give up
             */
            e.printStackTrace();
        }

    }
}

I don't think I can make it any simpler and still repeat the prompting for input until valid input is given. If there were many inputs being done I could break the logic out into an instance of the template pattern.

Sunday, February 20, 2011

all sub-sets of a set in java

I was offered the challenge to find all the sub-sets of a set, represented as an ordered list, using java.

I know a list isn't really a set, but it is the same idea in the end, since the elements are not repeated, also the non-recursive implementation I came up with would work equally well with sets as lists.

I started with a recursive implementation, and later found a non-recursive implementation with the same output.

First I made some tests to show what was going to happen.

package org.yi.happy.subset;

import static org.junit.Assert.assertEquals;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.junit.Test;

public class FindSubsetsTest {
    @Test
    public void testFindAll() {
        List<Integer> in = Arrays.asList(0,1,2,3);
        
        List<List<Integer>> have = FindSubsets.findAll(in);
        
        List<List<Integer>> want = new ArrayList<List<Integer>>();
        want.add(new ArrayList<Integer>());
        want.add(Arrays.asList(3));
        want.add(Arrays.asList(2));
        want.add(Arrays.asList(2, 3));
        want.add(Arrays.asList(1));
        want.add(Arrays.asList(1, 3));
        want.add(Arrays.asList(1, 2));
        want.add(Arrays.asList(1, 2, 3));
        want.add(Arrays.asList(0));
        want.add(Arrays.asList(0, 3));
        want.add(Arrays.asList(0, 2));
        want.add(Arrays.asList(0, 2, 3));
        want.add(Arrays.asList(0, 1));
        want.add(Arrays.asList(0, 1, 3));
        want.add(Arrays.asList(0, 1, 2));
        want.add(Arrays.asList(0, 1, 2, 3));

        assertEquals(want, have);
    }

    @Test
    public void testFindAllFlat() {
        List<Integer> in = Arrays.asList(0, 1, 2, 3);

        List<List<Integer>> have = FindSubsets.findAllFlat(in);

        List<List<Integer>> want = new ArrayList<List<Integer>>();
        want.add(new ArrayList<Integer>());
        want.add(Arrays.asList(3));
        want.add(Arrays.asList(2));
        want.add(Arrays.asList(2, 3));
        want.add(Arrays.asList(1));
        want.add(Arrays.asList(1, 3));
        want.add(Arrays.asList(1, 2));
        want.add(Arrays.asList(1, 2, 3));
        want.add(Arrays.asList(0));
        want.add(Arrays.asList(0, 3));
        want.add(Arrays.asList(0, 2));
        want.add(Arrays.asList(0, 2, 3));
        want.add(Arrays.asList(0, 1));
        want.add(Arrays.asList(0, 1, 3));
        want.add(Arrays.asList(0, 1, 2));
        want.add(Arrays.asList(0, 1, 2, 3));

        assertEquals(want, have);
    }
}

And the implementation, with implementation notes in it.

package org.yi.happy.subset;

import java.util.ArrayList;
import java.util.List;


public class FindSubsets {

    /**
     * Find all the subsets of in, recursively.
     * 
     * @param <T>
     *            the type of item items in the set.
     * @param in
     *            the set to get subsets off.
     * @return the list of subsets of in. The order is the same as doing binary
     *         counting with the least significant digit on the right.
     */
    public static <T> List<List<T>> findAll(List<T> in) {
        /*
         * we can do this recursively, we either exclude or include the first
         * item, and join all the deeper subsets to it.
         */

        if (in.size() == 0) {
            /*
             * the base case is just the empty set.
             */
            List<List<T>> out = new ArrayList<List<T>>();
            out.add(new ArrayList<T>());
            return out;
        }

        List<List<T>> out = new ArrayList<List<T>>();

        T first = in.get(0);
        List<List<T>> rest = findAll(in.subList(1, in.size()));

        /*
         * first all the sets excluding the first item
         */
        for (List<T> r : rest) {
            out.add(r);
        }

        /*
         * next all the sets including the first item
         */
        for (List<T> r : rest) {
            List<T> s = new ArrayList<T>();
            s.add(first);
            s.addAll(r);
            out.add(s);
        }

        return out;
    }

    /**
     * Find all the subsets of in, non-recursively.
     * 
     * @param <T>
     *            the type of item items in the set.
     * @param in
     *            the set to get subsets off.
     * @return the list of subsets of in.
     */
    public static <T> List<List<T>> findAllFlat(List<T> in) {
        List<List<T>> out = new ArrayList<List<T>>();
        out.add(new ArrayList<T>());

        for (T i : in) {
            List<List<T>> next = new ArrayList<List<T>>();
            for (List<T> j : out) {
                next.add(j);

                List<T> k = new ArrayList<T>(j);
                k.add(i);
                next.add(k);
            }
            out = next;
        }

        return out;
    }

}

It was not much harder than counting binary to make this list, I gave up on adding the restriction where the resulting lists of lists should be sorted.

Sunday, February 6, 2011

HTTP subversion access

The objective is restore the subversion repository URL space from my old web site. This will require making some subversion repositories available over HTTP using Apache 2.2. Authentication is required only for updates. Access to the repositories should be configured in the virtual host, and not globally.

The environment for the directions is Ubuntu 10.10 (Maverick Meerkat) Desktop freshly installed and updates done.

This example is for exposing multiple repositories under /svn in the URL space of a virtual host.

Install apache with the subversion module, and subversion:
sudo apt-get install apache2 libapache2-svn subversion

Make a home for the physical subversion repositories.
sudo mkdir /var/svn

And create a few repositories accessable to the web server:
sudo svnadmin create /var/svn/repos
sudo chown -R www-data:www-data /var/svn/repos
sudo svnadmin create /var/svn/repos2
sudo chown -R www-data:www-data /var/svn/repos2

create some users for authenticaton
sudo touch /var/svn/passwd
sudo htpasswd -bm /var/svn/passwd user1 pass1
sudo htpasswd -bm /var/svn/passwd user2 pass2

create the access control file /var/svn/access
[repos:/]
user1 = rw
* = r

[repos2:/]
user1 = rw
user2 = r
* =

Create a virtual host by creating /etc/apache2/sites-available/demo.local:
<VirtualHost *:80>
ServerName demo.local
ErrorLog ${APACHE_LOG_DIR}/demo.local-error.log
CustomLog ${APACHE_LOG_DIR}/demo.local-access.log combined

<Location /svn>
DAV svn
SVNParentPath /var/svn
SVNAutoVersioning On
AuthzSVNAccessFile /var/svn/access
Satisfy Any
Require valid-user
AuthType Basic
AuthName "Subversion repository"
AuthUserFile /var/svn/passwd
</Location>

</VirtualHost>

enable the virtual host
sudo a2ensite demo.local
sudo /etc/init.d/apache2 reload

At this point the repositories are available on the web server, and can be mounted using WebDAV. Extra details are in the SVN red book.