Wednesday, August 18, 2010

Thread Unsafety

#!/usr/bin/env python
import time,itertools
from threading import Thread

class FizzBuzz():
  g_place = ''
  def th(self, t, tminc, fn):
    start = time.clock()
    while True:
      t +=tminc
      while time.clock()<start+t: time.sleep(0.01)
      self.g_place = fn(self.g_place)
    
  def go(self, counter, printer):
    thds = ((0.7, 1.0, lambda c: printer(c)), 
      (0.0, 1.0, lambda c: counter.next()),
      (0.1, 3.0, lambda c: 'Fizz'), 
      (0.2, 5.0, lambda c: 'FizzBuzz' if c=='Fizz' else 'Buzz'))
    for thd in thds: Thread(target=self.th, args=thd).start()

def _print(s): print s
FizzBuzz().go(itertools.count(1), _print)
As far as I know, this is a unique way to code FizzBuzz. It's also a pretty bad way, for a variety of reasons. But at least it's multithreaded!

Saturday, August 14, 2010

Physics into audio

I've been toying with the idea of using physics simulations to generate audio.

First, imagine a audio in a circular loop, as on a record player. As the needle moves clockwise, the music plays. If the needle moves counter-clockwise, the music is played backwards. The faster the needle moves, the faster (and higher pitched) the sound.

Now, model the chaotic motion of a double pendulum, and use that as the needle that is driving the music:

It can also be interesting to use the data directly. Take a physics model of a double pendulum, and record the height (y) of the longer leg over time. Then, interpret that data as raw audio samples and play it!

Double pendulum as raw audio by jamonben

I inadvertently created a mashup while working on a related project, but it's not very good.

Monday, August 2, 2010

LnzScript 0.4

The LnzScript 0.4 release is here! This scripting tool can automate repetitve tasks in Windows, work with files and folders, and easily perform text manipulation.

The editor makes it easy to write quick one-off scripts. Standard output appears in a pane to the right. Let's say you have some text that you want shuffled randomly. If one were to write a Python script, you'd have to save the text in a temporary file, or load some library to access the Windows clipboard. With LnzScript, the clipboard is directly accessible without importing anything. One could just write Clipboard.set(Math.shuffleArray(Clipboard.get().split('\r\n'))) Furthermore, the LnzScript Editor can run a script before it has even been saved to a file, a unique feature, so you can run a script immediately.

LnzScript 0.4 includes more methods for working with files. File.dirListFiles(@'c:\myfolder', '*.txt','size') returns all of the text files in the directory, sorted by size. File.copyMany can copy full directories. File.createShortcut and File.getShortcutTarget can work with shortcuts. The Rename.renameFn will call a function you provide to rename files. To rename .jpeg to .jpg, say, all you need to do is:
File.cd(@'c:\myfolder');
Rename.rename('.jpeg','.jpg');

Rename.renamePreview can be used to see the results before renaming anything.

And, it's still good at automating tasks. I used it to access Webmail (for which there was not a 'remember me' option); much faster than typing in the fields every time. An old demo of LnzScript opening Firefox tabs is here.

The installer associates script files so that you can run them by double-clicking. Just by using argv in a script, you can now drag and drop a file into the script and it will run with that argument in argv[1], a 'droplet.' Lately I've been using Clavier+ to assign scripts to hotkeys. Other programs such as Launchy could also be used.

Why JavaScript? I find it to be much cleaner than Basic-derived semi-languages. Lambdas and the good parts can be very useful. I've added @'string' literals to the language, that can contain single backslashes, so that one can type @'c:\foo' instead of 'c:\\foo'. There are other additions like include(), alert(), print(), and argv.

Parsing .url shortcuts in a directory and printing out URLs:
File.cd(@'C:\folder');
var arFiles = File.dirListFiles('.', '*.url')
for(var i=0; i<arFiles.length;i++)
{
  var pageName = arFiles[i].slice(0,-4)
  var url = File.readFile(arFiles[i]).split('URL=')[1].split('\n')[0]
  print(pageName)
  print(url + '\n')  
}



An example using JavaScript's closures to rename files in the pattern 00, 01, 02, and so on, by last modification time:
include('<std>')
File.cd(@'C:\folder')
var i=0;
function renameNumbered(s)
{
  i++;
  return (i<10)?'0'+i+s : i+s;
}
//first, preview to see consequences
Rename.renameFnPreview(renameNumbered, 'time')
//then,
//Rename.renameFn(renameNumbered, 'time')