From a79414bcf14d17c58e040a7b8524f7bd8f7e5e03 Mon Sep 17 00:00:00 2001 From: Nat Lasseter Date: Mon, 22 Jan 2024 10:23:58 +0000 Subject: Migrate from gists --- NDFA2DFAexample | 32 +++++ README | 36 ++++++ Xmodmap | 10 ++ alleq.hs | 6 + box.mzn | 22 ++++ cpc/cpc1.rb | 23 ++++ cpc/cpc2.rb | 25 ++++ describe.rb | 47 +++++++ digits.rb | 43 +++++++ gen_object/a_cat.erl | 13 ++ gen_object/gen_object.erl | 31 +++++ gen_object/test_a_cat.erl | 11 ++ gitmove | 31 +++++ logcircle.rb | 28 +++++ make.rb | 314 ++++++++++++++++++++++++++++++++++++++++++++++ pdfbook4.rb | 34 +++++ scan.sh | 37 ++++++ section.c | 44 +++++++ slide.rb | 129 +++++++++++++++++++ stltogl | 21 ++++ sudoku.rb | 156 +++++++++++++++++++++++ tabelvortoj.rb | 101 +++++++++++++++ todo.vim | 6 + 23 files changed, 1200 insertions(+) create mode 100644 NDFA2DFAexample create mode 100644 README create mode 100644 Xmodmap create mode 100644 alleq.hs create mode 100644 box.mzn create mode 100644 cpc/cpc1.rb create mode 100644 cpc/cpc2.rb create mode 100644 describe.rb create mode 100644 digits.rb create mode 100644 gen_object/a_cat.erl create mode 100644 gen_object/gen_object.erl create mode 100644 gen_object/test_a_cat.erl create mode 100755 gitmove create mode 100644 logcircle.rb create mode 100644 make.rb create mode 100644 pdfbook4.rb create mode 100644 scan.sh create mode 100644 section.c create mode 100644 slide.rb create mode 100644 stltogl create mode 100644 sudoku.rb create mode 100644 tabelvortoj.rb create mode 100644 todo.vim diff --git a/NDFA2DFAexample b/NDFA2DFAexample new file mode 100644 index 0000000..53b8e77 --- /dev/null +++ b/NDFA2DFAexample @@ -0,0 +1,32 @@ +This example from http://en.wikipedia.org/wiki/Powerset_construction + +Comment: In the NDFA Extension to the VFSM syntax (VFSMv2N), lambda: and epsilon: are equivalent +Comment: In VFSMv2N, lambda: and epsilon: are special transitions indicating transition on no input +Start: 1 +Accept: 3 4 +Edges: + 1 0 2 + 1 lambda: 3 + 2 1 2 + 2 1 4 + 3 epsilon: 2 + 3 0 4 + 4 0 3 +End: + +Should become a DFA under powerset construction or equivalent + +Start: {123} +Accept: {123} {24} {23} {4} +Edges: + {123} 0 {24} + {123} 1 {24} + {24} 0 {23} + {24} 1 {24} + {23} 0 {4} + {23} 1 {24} + {4} 0 {23} + {4} 1 {} + {} 0 {} + {} 1 {} +End: diff --git a/README b/README new file mode 100644 index 0000000..5ed20e2 --- /dev/null +++ b/README @@ -0,0 +1,36 @@ +scan.sh: + Batch scanning script +digits.rb: + Digit combinations for target sum +gen_object/: + The start of an erlang OO behaviour +pdfbook4.rb: + Page order to make (or pdfjam command to turn a pdf file into) 4-up double-sided brochure ordered pages (to make two A6 folia per A4 page) +tabelvortoj.rb: + Tabelvortoj test +cpc/: + Cyclically Permutable Codewords +todo.vim: + Simple Vim Todo +describe.rb: + Describe the purpose of an executable +slide.rb: + A laser-cuttable circular slide rule generator +logcircle.rb: + Output cartesian coordinates for the tickmarks along a log scale around a circle +sudoku.rb: + Ruby ILP SAT sudoku solver +section.c: + Like the section command on IOS +Xmodmap: + Swap numbers and symbols on the numrow +make.rb: + Ruby script to make playing The Factory efficient (and thus boring) +box.mzn: + Intended to find the dimensions of a rectangle with an area at least n units and a ratio e. +NDFA2DFAexample: + NDFA to DFA example for VFSM +stltogl: + Vim Script to convert an STL file to openGL glVertex3f()s for inclusion in a c program +alleq.hs: + Haskell function to check all elements of a list are equal diff --git a/Xmodmap b/Xmodmap new file mode 100644 index 0000000..5ef003a --- /dev/null +++ b/Xmodmap @@ -0,0 +1,10 @@ +keycode 10 = exclam 1 exclam 1 onesuperior exclamdown onesuperior +keycode 11 = quotedbl 2 quotedbl 2 twosuperior oneeighth twosuperior +keycode 12 = sterling 3 sterling 3 threesuperior sterling threesuperior +keycode 13 = dollar 4 dollar 4 EuroSign onequarter EuroSign +keycode 14 = percent 5 percent 5 onehalf threeeighths onehalf +keycode 15 = asciicircum 6 asciicircum 6 threequarters fiveeighths threequarters +keycode 16 = ampersand 7 ampersand 7 braceleft seveneighths braceleft +keycode 17 = asterisk 8 asterisk 8 bracketleft trademark bracketleft +keycode 18 = parenleft 9 parenleft 9 bracketright plusminus bracketright +keycode 19 = parenright 0 parenright 0 braceright degree braceright diff --git a/alleq.hs b/alleq.hs new file mode 100644 index 0000000..7080614 --- /dev/null +++ b/alleq.hs @@ -0,0 +1,6 @@ +alleq :: Eq a => [a] -> Maybe a -> Bool +alleq [] _ = True +alleq (h:t) Nothing = alleq t (Just h) +alleq (h:t) (Just e) + | h == e = alleq t (Just e) + | True = False diff --git a/box.mzn b/box.mzn new file mode 100644 index 0000000..0fd6f44 --- /dev/null +++ b/box.mzn @@ -0,0 +1,22 @@ +include "globals.mzn"; + +% Given an integer n and a real e +par int: n = 566*708; +par float: e = 16/9; + +% Find two integers r <= c +var int: r; var int: c; +constraint c >= r; +output [ + "Rows: ", show(r), "\n", + "Columns: ", show(c), "\n" +]; + +% Such that (r-1)c < n <= rc +constraint + ((r-1)*c) < n + /\ + n <= (r*c); + +% And the ratio c/r is as close to e as possible. +solve minimize abs(c/r - e); diff --git a/cpc/cpc1.rb b/cpc/cpc1.rb new file mode 100644 index 0000000..1113de0 --- /dev/null +++ b/cpc/cpc1.rb @@ -0,0 +1,23 @@ +codewords = [] + +class Integer + def rotate_left(bits, width = bit_width) + bits %= width + (self << bits | self >> (width - bits)) & ((1 << width) - 1) + end +end + +(2**8).times do |candidate| + valid_candidate_p = true + 8.times do |bits| + rotated_candidate = candidate.rotate_left(bits, 8) + valid_candidate_p = false if codewords.include?(rotated_candidate) + end + codewords << candidate if valid_candidate_p +end + +p codewords +puts codewords.length + +#=> [0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 37, 39, 43, 45, 47, 51, 53, 55, 59, 61, 63, 85, 87, 91, 95, 111, 119, 127, 255] +#=> 36 diff --git a/cpc/cpc2.rb b/cpc/cpc2.rb new file mode 100644 index 0000000..54d05c6 --- /dev/null +++ b/cpc/cpc2.rb @@ -0,0 +1,25 @@ +BITS = 8 + +class Integer + def rotate_left(bits, width = bit_width) + bits %= width + (self << bits | self >> (width - bits)) & ((1 << width) - 1) + end +end + +candidates = (0...(2**BITS)).to_a + +(2**BITS).times do |candidate| + next if candidates[candidate].nil? + (1...BITS).each do |bits| + candidates[candidate.rotate_left(bits, BITS)] = nil + end +end + +codewords = candidates.compact + +p codewords +puts codewords.length + +#=> [1, 3, 5, 7, 9, 11, 13, 15, 19, 21, 23, 25, 27, 29, 31, 37, 39, 43, 45, 47, 53, 55, 59, 61, 63, 87, 91, 95, 111, 127] +#=> 30 diff --git a/describe.rb b/describe.rb new file mode 100644 index 0000000..38fabf9 --- /dev/null +++ b/describe.rb @@ -0,0 +1,47 @@ +#!/usr/bin/env ruby + +#!DESCRIBE: Describe the purpose of an executable + +require 'ptools' + +def fatal(filename, msg) + $stderr.puts("[ERR] #{filename}: #{msg}") + exit 1 +end + +filename = ARGV.shift + +fatal("???", "File name not given.") if filename.nil? + +unless File.exist?(filename) + ENV["PATH"].split(?:).each do |path| + test = File.join(path, filename) + if File.exist?(test) + filename = test + break + end + end +end + +basename = File.basename(filename) + +fatal(basename, "File does not exist.") unless File.exist?(filename) +fatal(basename, "File is not executable.") unless File.executable?(filename) +fatal(basename, "File is binary.") if File.binary?(filename) + +file = File.readlines(filename) + +describelines = file.select { |line| + line =~ /\A[#\/]*!DESCRIBE:/ + }.map { |line| + line.split("!DESCRIBE:")[1].strip + } + +fatal(basename, "File is indescribable!") if describelines.empty? + +puts "#{basename}: #{describelines[0]}" +describelines[1..-1].each { |line| + puts "#{" " * (basename.length + 2)}#{line}" +} + +#!DESCRIBE: Usage: describe FILE diff --git a/digits.rb b/digits.rb new file mode 100644 index 0000000..addc51e --- /dev/null +++ b/digits.rb @@ -0,0 +1,43 @@ +#!/usr/bin/env ruby + +require 'optimist' + +opts = Optimist::options do + version "digits 0.2 (c) 2023 Nat Lasseter" + banner <<-EOS +Digits gives valid combinations of digits 1-9 that sum to the given total + +Usage: + digits [opts] + +where [opts] are: +EOS + + opt :number, "The number of digits", type: :integer + opt :target, "The target sum", type: :integer + opt :exclude, "Exclude a digit", type: :integer, multi: true + opt :include, "Include a digit", type: :integer, multi: true + + educate_on_error +end + +digits = [1,2,3,4,5,6,7,8,9] +opts[:exclude].each { |i| digits.delete(i) } + +def puts_group(digits, mandatory, number, target = nil) + if target.nil? + puts digits.combination(number).select { |a| (mandatory - a).empty? }.sort { |a, b| a.sum <=> b.sum }.map { |a| "#{a.join} = #{a.sum}" } + else + puts digits.combination(number).select { |a| a.sum == target }.select { |a| (mandatory - a).empty? }.map { |a| "#{a.join} = #{target}" } + end +end + +if opts[:number_given] + puts "== #{opts[:number]} ==" + puts_group(digits, opts[:include], opts[:number], opts[:target]) +else + (2..8).each do |n| + puts "== #{n} ==" + puts_group(digits, opts[:include], n, opts[:target]) + end +end diff --git a/gen_object/a_cat.erl b/gen_object/a_cat.erl new file mode 100644 index 0000000..3e3b00f --- /dev/null +++ b/gen_object/a_cat.erl @@ -0,0 +1,13 @@ +% This is a cat. It behaves like a generic object. + +-module(a_cat). +-behaviour(gen_object). +-export([initialise/1, handle_message/3]). + +initialise([Name]) -> + {Name, "Meow"}. + +handle_message(say, [Word], {Name, Word}) -> + {Word, {Name, Word}}; +handle_message(say, _, State) -> + {"", State}. diff --git a/gen_object/gen_object.erl b/gen_object/gen_object.erl new file mode 100644 index 0000000..1990ec2 --- /dev/null +++ b/gen_object/gen_object.erl @@ -0,0 +1,31 @@ +% This is the behaviour definition for a generic object. + +-module(gen_object). +-export([new/2, delete/1, send/3]). + +-callback initialise(Args :: [any()]) -> State :: any(). +-callback handle_message(Msg :: atom(), Args :: [any()], State :: any()) -> {Response :: any(), New_State :: any()}. + +send(Obj, Msg, Args) -> + Obj ! {self(), Msg, Args}, + receive + Response -> + Response + end. + +new(CBM, Args) -> + State = apply(CBM, initialise, [Args]), + spawn(fun() -> loop(CBM, State) end). + +loop(CBM, State) -> + receive + gen_object__bif__exit -> + ok; + {From, Msg, Args} -> + {Resp, New_State} = apply(CBM, handle_message, [Msg, Args, State]), + From ! Resp, + loop(CBM, New_State) + end. + +delete(Obj) -> + Obj ! gen_object__bif__exit. diff --git a/gen_object/test_a_cat.erl b/gen_object/test_a_cat.erl new file mode 100644 index 0000000..589bb97 --- /dev/null +++ b/gen_object/test_a_cat.erl @@ -0,0 +1,11 @@ +% This is where we test the cat to make sure that it does not bark. + +-module(test_a_cat). +-export([main/0]). + +main() -> + MyCat = gen_object:new(a_cat, ["Fred"]), + FredSays = gen_object:send(MyCat, say, ["Woof"]), + gen_object:delete(MyCat), + + io:format("Fred says: ~p~n", [FredSays]). diff --git a/gitmove b/gitmove new file mode 100755 index 0000000..90a943d --- /dev/null +++ b/gitmove @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +#!DESCRIBE: Migrate repos to gitolite + +iam = "me" +from = "git@github.com:Me/" +to = "git@gitolite:" +repos = %w( ... ) + +File.open("repos.conf", ?w) do |f| + repos.each do |r| + f.puts "repo #{r}" + f.puts " RW+ = #{iam}" + end +end + +File.open("repos.script", ?w) do |f| + f.puts "#!/bin/bash" + repos.each do |r| + f.puts "git clone --bare #{from}#{r} __repo_#{r}" + f.puts "cd __repo_#{r}" + f.puts "git push --all #{to}#{r}" + f.puts "git push --tags #{to}#{r}" + f.puts "cd .." + f.puts "rm -rf __repo_#{r}" + f.puts + end +end + +File.chmod(0744, "repos.script") + +puts "Done generating; now push the contents of repos.conf to your gitolite config, then run the repos.script script." diff --git a/logcircle.rb b/logcircle.rb new file mode 100644 index 0000000..95d57ac --- /dev/null +++ b/logcircle.rb @@ -0,0 +1,28 @@ +#!/usr/bin/env ruby + +Maths = Math + +Intervals = ARGV.shift&.to_i || 2 +Radius = ARGV.shift&.to_i || 25 +Decimals = ARGV.shift&.to_i || 3 + +Scale = Maths::PI * 2 / Intervals +Width = 1 + Maths.log10(Radius).to_i + 1 + 1 + Decimals + +def a_tick(mantissa, exponent) + tick = mantissa * (10 ** exponent) + loc = Scale * (exponent + Maths.log10(mantissa)) + x = Radius * Maths.cos(loc) + y = Radius * Maths.sin(loc) + puts "%#{Intervals + 1}d: (%4.2fr) %#{Width}.#{Decimals}f %#{Width}.#{Decimals}f" % [tick, loc, x, y] +end + +puts "Max #{10 ** Intervals} (#{Intervals} intervals), radius #{Radius}, #{Decimals} decimals" + +Intervals.times do |exponent| + (1..9).each do |mantissa| + a_tick(mantissa, exponent) + end +end + +a_tick(1, Intervals) diff --git a/make.rb b/make.rb new file mode 100644 index 0000000..a066927 --- /dev/null +++ b/make.rb @@ -0,0 +1,314 @@ +#!/usr/bin/env ruby + +require 'json' +Products = JSON.parse(DATA.read) +Productindex = Products.keys + +ingredientsstack = [] +buildstack = {} + +build = ARGV.shift +if build.nil? then + puts "Build what?" + exit 1 +end + +quantity = ARGV.shift +if quantity.nil? then + quantity = 1 +else + quantity = quantity.to_i +end + +ingredientsstack.push build + +while ingredientsstack.count > 0 do + build = ingredientsstack.pop + product = Products[build] + if product.nil? then + puts "#{build} is not a product" + exit 1 + end + product.each do |key, value| + value.times do + ingredientsstack.push key + end + end + if buildstack[build].nil? then + buildstack[build] = 1 + else + buildstack[build] += 1 + end +end + +buildstack.keys.sort { |a, b| + Productindex.index(a) <=> Productindex.index(b) +}.each do |key| + puts "%4d: %s" % [buildstack[key] * quantity, key] +end + +__END__ +{ + "Cardboard": {}, + "Concrete": {}, + "Magnet": {}, + "Metal": {}, + "Paint": {}, + "Plastic": {}, + "Rare metal": {}, + "Rubber": {}, + "Wire": {}, + + "Adv concrete": { + "Concrete": 2, + "Metal": 2 + }, + "Belt": { + "Rubber": 2 + }, + "Box": { + "Cardboard": 4 + }, + "Cable": { + "Metal": 1 + }, + "Circuit": { + "Plastic": 2, + "Wire": 1 + }, + "Gear": { + "Metal": 2 + }, + "Hose": { + "Rubber": 2 + }, + "Metal wheel": { + "Metal": 2 + }, + "Motor": { + "Magnet": 2, + "Metal": 1, + "Wire": 2 + }, + "Plastic wheel": { + "Plastic": 2 + }, + "Pump": { + "Metal": 2, + "Plastic": 1, + "Rubber": 1 + }, + "Garden gnome": { + "Concrete": 1, + "Paint": 1, + "Box": 1 + }, + "Speakers": { + "Magnet": 2, + "Plastic": 2, + "Wire": 1, + "Box": 1 + }, + "Toaster": { + "Metal": 2, + "Wire": 2, + "Box": 1 + }, + "Air gun": { + "Metal": 4, + "Hose": 2 + }, + "Arm": { + "Metal": 2, + "Circuit": 1, + "Motor": 2 + }, + "Conveyor": { + "Belt": 1, + "Gear": 2, + "Metal wheel": 8, + "Motor": 1 + }, + "Lifter": { + "Metal": 3, + "Cable": 2, + "Hose": 2, + "Motor": 1, + "Pump": 1 + }, + "Logic unit": { + "Wire": 5, + "Circuit": 4 + }, + "Mover": { + "Metal": 3, + "Gear": 4, + "Metal wheel": 4, + "Motor": 2 + }, + "Road": { + "Concrete": 4, + "Adv concrete": 2 + }, + "Support": { + "Metal": 2, + "Adv concrete": 2 + }, + "Thing-a-ma-jig": { + "Circuit": 3, + "Hose": 2, + "Motor": 1, + "Pump": 2 + }, + "Widget": { + "Metal": 1, + "Plastic": 4, + "Wire": 2, + "Circuit": 1 + }, + "Toy car": { + "Metal": 1, + "Paint": 1, + "Plastic": 3, + "Plastic wheel": 4, + "Box": 1 + }, + "Water gun": { + "Paint": 1, + "Plastic": 6, + "Hose": 2, + "Box": 1 + }, + + "Adv logic unit": { + "Wire": 4, + "Circuit": 4, + "Logic unit": 2 + }, + "Assembly line": { + "Air gun": 2, + "Arm": 2, + "Conveyor": 3, + "Lifter": 1, + "Mover": 1 + }, + "Jet engine": { + "Metal": 8, + "Wire": 12, + "Hose": 6, + "Pump": 4, + "Thing-a-ma-jig": 1 + }, + "Sensor": { + "Rare metal": 2, + "Wire": 1, + "Circuit": 1, + "Logic unit": 1 + }, + "Bridge": { + "Road": 6, + "Support": 6 + }, + "Forklift": { + "Metal": 6, + "Rubber": 8, + "Metal wheel": 4, + "Motor": 2, + "Box": 4 + }, + "Radio tower": { + "Metal": 12, + "Wire": 6, + "Support": 4 + }, + "Tablet computer": { + "Plastic": 1, + "Wire": 3, + "Circuit": 3, + "Logic unit": 1, + "Box": 1 + }, + + "Drone": { + "Plastic": 4, + "Rare metal": 1, + "Motor": 4, + "Adv logic unit": 1, + "Sensor": 2 + }, + "Jet": { + "Metal": 24, + "Wire": 18, + "Adv logic unit": 6, + "Jet engine": 4, + "Sensor": 8 + }, + "Oculus rift": { + "Plastic": 2, + "Rare metal": 2, + "Wire": 4, + "Widget": 2, + "Sensor": 2 + }, + + "Builder: Tier 1": { + "Motor": 1, + "Arm": 2, + "Conveyor": 1, + "Thing-a-ma-jig": 1 + }, + "Builder: Tier 2": { + "Motor": 1, + "Arm": 3, + "Conveyor": 1, + "Thing-a-ma-jig": 1, + "Widget": 2 + }, + "Builder: Tier 3": { + "Logic unit": 1, + "Thing-a-ma-jig": 1, + "Widget": 4, + "Assembly line": 1 + }, + "Builder: Tier 4": { + "Widget": 2, + "Adv logic unit": 2, + "Assembly line": 1, + "Sensor": 6 + }, + "Builder: Builders": { + "Arm": 2, + "Logic unit": 1, + "Thing-a-ma-jig": 4, + "Widget": 1, + "Assembly line": 1 + }, + "Builder: Taskers": { + "Thing-a-ma-jig": 2, + "Widget": 2, + "Adv logic unit": 1, + "Assembly line": 1 + }, + "Builder: Universal": { + "Arm": 4, + "Thing-a-ma-jig": 2, + "Widget": 4, + "Adv logic unit": 2, + "Assembly line": 2 + }, + + "Tasker: Purchasing": { + "Paint": 1, + "Wire": 6, + "Circuit": 4, + "Logic unit": 1, + "Widget": 1 + }, + "Tasker: Sales": { + "Paint": 1, + "Wire": 8, + "Logic unit": 2, + "Widget": 1, + "Adv logic unit": 1 + } +} diff --git a/pdfbook4.rb b/pdfbook4.rb new file mode 100644 index 0000000..e7f66d2 --- /dev/null +++ b/pdfbook4.rb @@ -0,0 +1,34 @@ +#!/usr/bin/env ruby + +n = ARGV.shift.to_i +m = n +m = ((m / 8) + 1) * 8 if m % 8 != 0 + +p = (1..n).map(&:to_s) + ["{}"] * (m - n) +o = [] + +until p.empty? do + t1 = [] + t2 = [] + + t1.push(p.pop) + t1.push(p.shift) + t2.push(p.shift) + t2.push(p.pop) + + t1.push(p.pop) + t1.push(p.shift) + t2.push(p.shift) + t2.push(p.pop) + + o += t1 + o += t2 +end + +f = ARGV.shift + +if f.nil? + puts o.join(?,) +else + puts "pdfjam --nup 2x2 -o #{File.basename(f, ".*")}-book.pdf #{f} #{o.join(?,)}" +end diff --git a/scan.sh b/scan.sh new file mode 100644 index 0000000..ecb505c --- /dev/null +++ b/scan.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +function scanpage { + echo -n insert $1 and press return + read + scanimage \ + -d 'brother5:bus2;dev2' \ + --AutoDocumentSize=yes \ + --format=pdf \ + --resolution 300 \ + --AutoDeskew=yes \ + -o $1 2>/dev/null +} + +if [[ -z $1 ]] ; then + echo -n 'prefix ?' + read pref + [[ -z $pref ]] && exit +else + pref=$1 + shift +fi + +if [[ -z $1 ]] ; then + while true ; do + echo -n 'document#(s) ?' + read n + [[ -z $n ]] && exit + for j in $n ; do + scanpage ${pref}-$j.pdf + done + done +else + for j in $* ; do + scanpage ${pref}-$j.pdf + done +fi diff --git a/section.c b/section.c new file mode 100644 index 0000000..eaefcbd --- /dev/null +++ b/section.c @@ -0,0 +1,44 @@ +#include +#include +#include + +int main(int argc, char** argv) { + regex_t* preg; + int reti; + char* linebuf; + char insection; + + if(argc != 2) { + fprintf(stderr, "Usage: section \n"); + return 1; + } + + reti = regcomp(preg, argv[1], REG_EXTENDED); + if (reti) { + fprintf(stderr, "Could not compile regex\n"); + return 1; + } + + linebuf = (char*) calloc(4096, sizeof(char)); + insection = 0; + + while (fgets(linebuf, 4096, stdin) != NULL) { + if (insection) { + if (linebuf[0] != ' ' && linebuf[0] != '\t') { + insection = 0; + } else + fprintf(stdout, "%s", linebuf); + } else { + if (linebuf[0] != ' ' && linebuf[0] != '\t') { + reti = regexec(preg, linebuf, 0, NULL, 0); + if (!reti) { + fprintf(stdout, "---\n%s", linebuf); + insection = 1; + } + } + } + } + + free(linebuf); + regfree(preg); +} diff --git a/slide.rb b/slide.rb new file mode 100644 index 0000000..46505aa --- /dev/null +++ b/slide.rb @@ -0,0 +1,129 @@ +#!/usr/bin/env ruby + +Maths = Math + +Radius = ARGV.shift&.to_f || 50.0 +Ring = ARGV.shift&.to_f || 15.0 + +Decimals = 6 +Origin_x = Radius + Ring + 1 +Origin_y = Radius + Ring + 1 + +Page_x = 2 * 2 * Origin_x +Page_y = 2 * Origin_y + +def a_preamble(page_x, page_y) + puts <<-EOT % [page_x, page_y, page_x, page_y] + + + + + EOT +end + +def a_postamble + puts <<-EOT + + + EOT +end + +def a_circle(origin_x, origin_y, radius) + puts <<-EOT % [origin_x, origin_y, radius, radius] + + EOT +end + +def a_mark(xf, yf, xt, yt) + puts <<-EOT % [xf, yf, xt, yt] + + EOT +end + +def a_label(origin_x, origin_y, radius, heading, mod, ticktext) + xt = origin_x + (radius * Maths.cos(heading) * (1 + mod)) + yt = origin_y + (radius * Maths.sin(heading) * (1 + mod)) + puts <<-EOT % [xt, yt, ticktext] + %s + EOT +end + +def a_double_label(origin_x, origin_y, radius, heading, mod, ticktext) + a_label(origin_x, origin_y, radius, heading, -mod, ticktext) + a_label(origin_x, origin_y, radius, heading, mod, ticktext) +end + +def a_tick(mantissa, exponent, origin_x, origin_y, radius, intervals) + scale = Maths::PI * 2 / intervals + (0..0.9).step(0.1).each do |sub| + tick = mantissa * (10 ** exponent) + sub + heading = scale * (exponent + Maths.log10(mantissa + sub)) + + adj = case mantissa + sub + when *[1.0,5.0] + 0.06 + when *[2.0,3.0,4.0,6.0,7.0,8.0,9.0] + 0.04 + else + 0.02 + end + xi = origin_x + (radius * Maths.cos(heading) * (1 - adj)) + yi = origin_y + (radius * Maths.sin(heading) * (1 - adj)) + xo = origin_x + (radius * Maths.cos(heading) * (1 + adj)) + yo = origin_y + (radius * Maths.sin(heading) * (1 + adj)) + + ticktext = if tick == 1.0 + "#{tick.to_i}(#{"0" * intervals})" + else + "#{tick.to_i}" + end + + a_mark(xi, yi, xo, yo) + a_double_label(origin_x, origin_y, radius, heading, adj + 0.04, ticktext) if sub == 0 + end +end + +def a_scale(origin_x, origin_y, radius, intervals) + intervals.times do |exponent| + (1..9).each do |mantissa| + a_tick(mantissa, exponent, origin_x, origin_y, radius, intervals) + end + end +end + +a_preamble(Page_x + 1, Page_y + 1) + +a_circle(Origin_x, Origin_y, Radius) +a_circle(Origin_x, Origin_y, Radius + Ring) +a_circle(Origin_x + (2 * (Radius + Ring + 1)), Origin_y, Radius + Ring) +a_circle(Origin_x, Origin_y, Radius - Ring) + +a_double_label(Origin_x, Origin_y, Radius - Ring, 0.05, 0.1, "x") +a_scale(Origin_x, Origin_y, Radius - Ring, 1) + +a_double_label(Origin_x, Origin_y, Radius, 0.04, 0.1, "x^2") +a_scale(Origin_x, Origin_y, Radius, 2) + +a_postamble diff --git a/stltogl b/stltogl new file mode 100644 index 0000000..5c75287 --- /dev/null +++ b/stltogl @@ -0,0 +1,21 @@ +"Get rid of most of the bumpf in the file +:g/solid/d +:g/loop/d +:g/endfacet/d +"Get rid of leading and trailing spaces +:%s/^ *//g +:%s/ *$//g +"Unify spaces +:%s/ \+/ /g +"Rewrite each facet normal into a glNormal3f +:%s/facet normal /glNormal3f(/g +"Rewrite each vertex into a glVertex3f +:%s/vertex /glVertex3f(/g +"Rewrite line endings into function endings +"and separate arguments +:%s/$/);/g +:%s/ /, /g +"Colour each vertex +:%s/\v(glV.*\n)(glV.*\n)(glV.*\n)/glColor3f(1.0, 0.0, 0.0); \1glColor3f(0.0, 1.0, 0.0); \2glColor3f(0.0, 0.0, 1.0); \3/g +"Get rid of blank lines +:g/^$/d diff --git a/sudoku.rb b/sudoku.rb new file mode 100644 index 0000000..9ac93c0 --- /dev/null +++ b/sudoku.rb @@ -0,0 +1,156 @@ +class Variable + def initialize(domain) + @domain = domain + end + + def fixed? + if @domain.length == 1 + @domain[0] + else + false + end + end + + def include?(x) + @domain.include?(x) + end + + def fix(x) + @domain = [x] + end + + def eliminate(x) + @domain.delete(x) unless fixed? + end +end + +def sudokuprint(grid, subsize, size = subsize * subsize) + w = Math.log10(size).ceil + + bar = '┼ ┼' + (('─' * (subsize * (w + 1) + 1) + '┼') * subsize + ' ┼') * subsize + + puts bar + puts bar + (0...size).step(subsize).each do |rs| + (rs...(rs + subsize)).each do |r| + (1..size).step(subsize).each do |ds| + print '│ │ ' + (0...size).step(subsize).each do |b| + (b...(b + subsize)).each do |c| + (ds...(ds + subsize)).each do |d| + print (grid[r][c].include?(d) ? ("%#{w}d" % d) : (' ' * w)) + ' ' + end + print '│ ' + end + print '│ ' + end + puts + end + puts bar + end + puts bar + end +end + +SUBSIZE = 3 +SIZE = SUBSIZE * SUBSIZE + +boxes = [] +(0...SIZE).step(SUBSIZE).each do |r| + (0...SIZE).step(SUBSIZE).each do |c| + boxes.push([r, c]) + end +end + +grid = Array.new(SIZE) { + Array.new(SIZE) { + Variable.new((1..SIZE).to_a) + } +} + +grid[0][3].fix(2) +grid[0][4].fix(9) +grid[0][5].fix(4) +grid[0][6].fix(3) +grid[0][8].fix(5) + +grid[1][0].fix(9) +grid[1][1].fix(5) +grid[1][3].fix(6) +grid[1][5].fix(8) +grid[1][6].fix(7) +grid[1][8].fix(2) + +grid[2][2].fix(3) +grid[2][7].fix(8) + +grid[3][1].fix(8) +grid[3][8].fix(4) + +grid[4][1].fix(6) +grid[4][3].fix(9) +grid[4][5].fix(1) +grid[4][7].fix(7) + +grid[5][0].fix(4) +grid[5][7].fix(5) + +grid[6][1].fix(1) +grid[6][6].fix(2) + +grid[7][0].fix(2) +grid[7][2].fix(6) +grid[7][3].fix(5) +grid[7][5].fix(3) +grid[7][7].fix(9) +grid[7][8].fix(8) + +grid[8][0].fix(3) +grid[8][2].fix(7) +grid[8][3].fix(1) +grid[8][4].fix(8) +grid[8][5].fix(2) + +until grid.flatten.count(&:fixed?) == 81 + (0...SIZE).each do |i| + row = grid[i] + row.each do |cell| + if v = cell.fixed? + row.each do |c2| + c2.eliminate(v) + end + end + end + end + + (0...SIZE).each do |i| + col = grid.map { |row| row[i] } + col.each do |cell| + if v = cell.fixed? + col.each do |c2| + c2.eliminate(v) + end + end + end + end + + (0...SIZE).each do |i| + rs, cs = boxes[i] + box = [] + (rs...(rs + SUBSIZE)).each do |r| + (cs...(cs + SUBSIZE)).each do |c| + box.push(grid[r][c]) + end + end + + box.each do |cell| + if v = cell.fixed? + box.each do |c2| + c2.eliminate(v) + end + end + end + end +end + +sudokuprint(grid, SUBSIZE, SIZE) diff --git a/tabelvortoj.rb b/tabelvortoj.rb new file mode 100644 index 0000000..2e85ccd --- /dev/null +++ b/tabelvortoj.rb @@ -0,0 +1,101 @@ +#!/usr/bin/env ruby + +#!DESCRIBE: Flash cards for table words + +require "io/console" + +data = DATA.each_line.map { |l| l.strip.split(?;) } +correct = 0 +total = 0 + +loop do + get = data.sample(4) + if rand(2).zero? + qn = get.first.first + ans = get.first.last + opts = get.map(&:last).shuffle + else + qn = get.first.last + ans = get.first.first + opts = get.map(&:first).shuffle + end + + print <<-EOT.chop + +#{qn} + + 1: #{opts[0]} + 2: #{opts[1]} + 3: #{opts[2]} + 4: #{opts[3]} + +>: +EOT + + r = $stdin.getch.to_i + + break unless r > 0 && r < 5 + + print "#{r} " + if ans == opts[r - 1] + puts ?✔ + correct += 1 + else + puts ?✘ + end + + total += 1 +end + +puts <<-EOT + + +Score: #{correct}/#{total} +EOT + +__END__ +kio;what +tio;that +io;something +ĉio;everything +nenio;nothing +kiu;who, which +tiu;that person, that one +iu;someone +ĉiu;everyone, every +neniu;no-one, none of them +kiam;when +tiam;then +iam;some time, ever +ĉiam;always, every time +neniam;never, no time +kia;what kind of +tia;that kind of +ia;some kind of +ĉia;every kind of +nenia;no kind of +kie;where +tie;there +ie;somewhere +ĉie;everywhere +nenie;nowhere +kiel;how +tiel;like that, thus +iel;in some way +ĉiel;in every way +neniel;in no way +kiom;how much +tiom;that much +iom;to some extent, a certain amount +ĉiom;all of it, the whole amount +neniom;none of it, no amount +kial;why +tial;for that reason +ial;for some reason +ĉial;for every reason +nenial;for no reason +kies;whose +ties;their, that one's +ies;someone's +ĉies;everyone's +nenies;no-one's diff --git a/todo.vim b/todo.vim new file mode 100644 index 0000000..96dc38f --- /dev/null +++ b/todo.vim @@ -0,0 +1,6 @@ +"In normal mode, [ positions the cursor in the checkbox and waits for a character with which to replace the checkmark. +au FileType todo nnoremap [ 0t]r +"In insert mode, [ actually inserts a checkbox and a space. +au FileType todo inoremap [ [] +"Any file with a name ending in todo is a todo file. +au BufRead,BufNewFile *todo set ft=todo -- cgit v1.2.1