diff options
author | Nat Lasseter <nat.lasseter@york.ac.uk> | 2024-01-22 10:23:58 +0000 |
---|---|---|
committer | Nat Lasseter <nat.lasseter@york.ac.uk> | 2024-01-22 10:23:58 +0000 |
commit | a79414bcf14d17c58e040a7b8524f7bd8f7e5e03 (patch) | |
tree | 4f2f232aca568711ecb35caa3444b54f4dfa4361 |
Migrate from gists
-rw-r--r-- | NDFA2DFAexample | 32 | ||||
-rw-r--r-- | README | 36 | ||||
-rw-r--r-- | Xmodmap | 10 | ||||
-rw-r--r-- | alleq.hs | 6 | ||||
-rw-r--r-- | box.mzn | 22 | ||||
-rw-r--r-- | cpc/cpc1.rb | 23 | ||||
-rw-r--r-- | cpc/cpc2.rb | 25 | ||||
-rw-r--r-- | describe.rb | 47 | ||||
-rw-r--r-- | digits.rb | 43 | ||||
-rw-r--r-- | gen_object/a_cat.erl | 13 | ||||
-rw-r--r-- | gen_object/gen_object.erl | 31 | ||||
-rw-r--r-- | gen_object/test_a_cat.erl | 11 | ||||
-rwxr-xr-x | gitmove | 31 | ||||
-rw-r--r-- | logcircle.rb | 28 | ||||
-rw-r--r-- | make.rb | 314 | ||||
-rw-r--r-- | pdfbook4.rb | 34 | ||||
-rw-r--r-- | scan.sh | 37 | ||||
-rw-r--r-- | section.c | 44 | ||||
-rw-r--r-- | slide.rb | 129 | ||||
-rw-r--r-- | stltogl | 21 | ||||
-rw-r--r-- | sudoku.rb | 156 | ||||
-rw-r--r-- | tabelvortoj.rb | 101 | ||||
-rw-r--r-- | todo.vim | 6 |
23 files changed, 1200 insertions, 0 deletions
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: @@ -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 @@ -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 @@ -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]). @@ -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) @@ -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 @@ -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 <regex.h> +#include <stdio.h> +#include <stdlib.h> + +int main(int argc, char** argv) { + regex_t* preg; + int reti; + char* linebuf; + char insection; + + if(argc != 2) { + fprintf(stderr, "Usage: section <REGEX>\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] +<?xml version="1.0" encoding="UTF-8" standalone="no"?> + +<svg + width="%dmm" + height="%dmm" + viewBox="0 0 %d %d" + version="1.1" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" +> + <g> + EOT +end + +def a_postamble + puts <<-EOT + </g> +</svg> + EOT +end + +def a_circle(origin_x, origin_y, radius) + puts <<-EOT % [origin_x, origin_y, radius, radius] + <ellipse + style="fill:none;stroke:#FF0000;stroke-width:0.1" + cx="%.6f" + cy="%.6f" + rx="%.6f" + ry="%.6f" + /> + EOT +end + +def a_mark(xf, yf, xt, yt) + puts <<-EOT % [xf, yf, xt, yt] + <path + style="fill:none;stroke:#0000FF;stroke-width:0.1" + d="M %.6f,%.6f %.6f,%.6f" + /> + 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] + <text + xml:space="preserve" + style="fill:#000000;stroke:none;font-size:1.5px;font-family:'Google Sans'" + x="%.6f" + y="%.6f" + text-anchor="middle" + >%s</text> + 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 @@ -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 [ [<Space>]<Space> +"Any file with a name ending in todo is a todo file. +au BufRead,BufNewFile *todo set ft=todo |