Skip to content

Instantly share code, notes, and snippets.

@maxrothman
maxrothman / core.clj
Created October 26, 2020 03:58
Dump Microsoft SQL database as CSV
(ns help-dad.core
(:require [clojure.java.jdbc :as jdbc]
[clojure.java.io :as io]
[clojure.data.csv :as csv])
(:gen-class))
;; Assumed directory layout:
;; - table-names A text file with one table name per line. You have to produce this manually
;; - dumps/ An empty directory where the CSVs will go
;; - help-dad/ The project, as per the `lein new app` template
@maxrothman
maxrothman / git-diff-blame.py
Created December 31, 2019 00:44
Git diff + blame
#!/usr/bin/env python3
"""
Imagine this: you do a bunch of work and end up with a bunch of commits on a branch, but now you
want to reorganize them into logical changes. A lot of those commits touched the same lines though,
so it's hard to know how to squash them together. In this situation, it'd be helpful to look at the
whole diff of the branch against its root, which changes labeled by the commit that introduces them,
sort of like a hybrid between git blame and git diff. This is that!
Usage: git diff --color=always ROOT | git-diff-blame.py | less
@maxrothman
maxrothman / README.md
Last active October 6, 2019 02:01
Book diffing

Book diffing

This code was written when a new edition of a book series I like came out and I wanted to find out what was different between the old and new versions. The goal was to create readable diffs of English prose so that I could scan through the books and easily see what was different.

Most of the diffing tools out there are built with the assumption that their target texts are source code, or some other machine-optimized format, not prose, so I had to build some of my own tools.

The format that I found most readable had the following features:

@maxrothman
maxrothman / README.md
Last active June 20, 2021 18:45
Music searching

Music searching

This gist contains some tools I wrote to solve a problem I ran into when archiving folk tunes. Once I had 30+ tunes in the archive, it became hard to tell whether any particular tune I came across was already in the archive or not, and I'm usually not able to remember a tune note-for-note. The solution to this problem was to build a tool that could search for music scores based on an approximately-similar snippet.

Details

These tools are tuned to my particular setup, but the core should be generalizable. Here are the assumptions the code makes:

  • Scores are stored as compressed MusicXML (.mxl) files
  • The scores and both scripts are stored in the same directory
@maxrothman
maxrothman / wait-for-status.sh
Created March 27, 2017 18:09
Wait for a PR to pass tests
#!/usr/bin/env bash
USAGE="Usage: wait-on-status OWNER REPO PR#"
[ -z $1 ] || [ -z $2 ] || [ -z $3 ] && echo $USAGE && exit 2
state="pending"
inloop=false
while [[ "$state" = "pending" ]]; do
$inloop && sleep 60
sha=$(curl -s https://api.github.com/repos/$1/$2/pulls/$3/commits | jq -r '.[-1].sha')
state=$(curl -s https://api.github.com/repos/$1/$2/commits/$sha/status | jq -r '.state')
#!/bin/bash
urls = (url1.com localhost:2323 'home page.com')
for url in ${urls[*]}; do
curl $url 2>&1 > $url.html
if [$? > 0]; then
echo something bad happened!
rm $url.html
done
for file in $(ls *.html); do
if [grep "I wish I had $20" $file]; then
@maxrothman
maxrothman / maze.py
Created July 11, 2016 16:15
Maze-solving exercise using turtle
"""
A maze-solving exercise using the "turtle" module.
The student should implement a new function and make it be executed in the indicated place at the bottom of the module.
The function should use "turtle.peek()", "turtle.forward()", "turtle.left()", and "turtle.right()", but the arguments to
"left" and "right" should be divisible by 90.
Monkey-patches "peek" and "forward" in "turtle" to address the fact that a turtle can't get the color of the pixel beneath it
and to restrict movement to the grid.
"""
@maxrothman
maxrothman / rename-replset.yml
Created October 28, 2015 20:02
An Ansible playbook that changes the name of a mongo replication set
# Renames a mongo replication set
# This necessarily resyncs the secondaries, taking them offline, but total downtime on the primary should be short.
#
# Usage:
# ansible-playbook rename_replset.yml -e 'password=SuperSecretAdminPassword name=new_replset_name' -i host1,host2,host3
#
# Note: the first host in the specified inventory will become the new primary
- hosts: all
vars:
@maxrothman
maxrothman / chopsticks.py
Last active August 29, 2015 14:19
chopsticks solution
"""
Solution for the game chopsticks (http://en.wikipedia.org/wiki/Chopsticks_(hand_game)) with even splitting only
Requrements: collections-extended
Future work:
- find subset of tree where the game halts
- remove "dumb moves", i.e. moves where a player COULD win but doesn't
- investigate deterministic lines, e.g. when the "only intelligent" move leads on a deterministic path
- investigate avoiding "dumb moves" with lookahead
"""
@maxrothman
maxrothman / gist:ddaf202a4604533bf717
Last active August 29, 2015 14:15
Sierpinski triangles
"""
Usage: test.py [l|c|r] <n>
Print a Sierpinski's Gasket of iteration n, left, center, or right-aligned (accordingly)
"""
import string, sys
def sierpinski(n, c):
gasket = [c]
for i in range(1, n+1):
gasket += ['{0}{0:>{1}}'.format(j, 2**i) for j in gasket]