notes
Here are my notes on some very varied topics.
The difference between my main page posts and my notes is that I’ll often reorganize and extend my notes.
-
modified January 10, 2021.
ten-second guide to video compression
compression generally requires sacrificing quality, since most video codecs are plenty good at compressing.
this is my default:
ffmpeg -i in.mp4 -map_metadata -1 -vf scale=800:-1 -crf 28 -c:a copy out.mp4
more details
you generally want to set a higher
crf
(bitrate). default is23
, below17
is visually non-lossy, every+6
is half the bitrate. the-c:a copy
copies audio stream.ffmpeg -i in.mp4 -crf 28 -c:a copy out.mp4
also consider removing all metadata
ffmpeg -i in.mp4 -map_metadata -1 -c:v copy -c:a copy out.mp4
also consider scaling down the video (
-1
means “whatever value keeps it proportional”)ffmpeg -i in.mp4 -vf scale=800:-1 -c:a copy out.mp4
also consider changing the encoding speed to compression ratio. from low compression to high compression, you have:
ultrafast
,superfast
,veryfast
,faster
,fast
,medium
(default),slow
,slower
,veryslow
ffmpeg -i in.mp4 -preset slow -c:a copy out.mp4
also consider changing to a newer codec, though this sacrifices compatability with many players (default is
-c:v libx264
)ffmpeg -i in.mp4 -c:v libx265 -c:a copy out.mp4
and here’s the do-everything command:
ffmpeg -i in.mp4 -crf 28 -map_metadata -1 -vf scale=800:-1 -preset slow -c:v libx265 -c:a copy out.mp4
ten-second guide to video compression (permalink) (tweet)
-
modified February 9, 2021.
the no-JavaScript necronomicon
A book of CSS maledictions. A song for the glory and abuse of CSS. A perverse guide for the day-to-day CSS reprobate. Here I collect a bunch of links about implementing traditionally-JS features without using JS.
- Toggles with saved state: Embed a hidden checkbox somewhere in your page, and make the toggle button a
<label>
tag. Write CSS to style your element one way when the checkbox is:checked
, and another when the checkbox is not:checked
. Clicking the<label>
activates the toggle. Since most browsers save checkbox state when navigating, you get this toggle state saved for free. - Lazy-loading images with blur preview: Couldn’t find the link for this post, but the idea was to deliver the image as a CSS background. Have the initial background be the low-res blurred version, but write CSS to animate the background using the high-res version as the second keyframe, with an instantaneous timing function. As a result, the low-res keyframe is immediately replaced with the second high-res keyframe when it loads.
- Live server push without JS: The idea is to serve a video (specifically, MJPEG) which lazily fetches its later frames. Then hook up your server to send future frames dynamically. The end effect is an image that updates automatically as the server pushes content in the form of video frames. The example given is a no-JS counter which shows the current number of visitors on the site.
- Round or take mod of a numeric CSS variable: generally you can only simulate rounding if you can truncate, and you can’t truncate with
calc
. Unless you multiply and divide by the smallest positive number representable by a double, that is:--shf: 4.9406564584124654e-324;
. The same trick can be used to perform modulo. It’s super cursed, so here, the equivalent ofcalc(a mod b)
is:
the no-JavaScript necronomicon (permalink) (tweet)--a-mod-b: calc(var(--a) - (var(--a) / var(--b) * var(--shf) / var(--shf) * var(--b)));
- Toggles with saved state: Embed a hidden checkbox somewhere in your page, and make the toggle button a
-
modified June 25, 2020.
commands.md
tags: linux
I keep around a file called
commands.md
which is a gigantic list of tiny how-tos. Whenever I catch myself spending forever finding the right commands to run, I add to this list.Here are some of those how-tos that I find myself referencing all the time. (newest first)
Compress pngs
for file in *.png; do pngcrush -ow "$file"; done
Compress gifs
gifsicle -O3 --colors 256 --batch -i *.gif
Setting up swap
Storing 1024 * 1M of swap in
/var/swap.1
sudo /bin/dd if=/dev/zero of=/var/swap.1 bs=1M count=1024 sudo chmod 0600 /var/swap.1 sudo /sbin/mkswap /var/swap.1
Enable:
sudo /sbin/swapon /var/swap.1
Add to
/etc/fstab
to start swap on boot:/var/swap.1 swap swap defaults 0 0
(from https://stackoverflow.com/a/17173973)
Set a debugger breakpoint before page reload
addEventListener('beforeunload',()=>{debugger})
Patch pip packages from source
e.g. for
https://github.com/rkern/line_profiler
:git clone https://github.com/rkern/line_profiler.git find line_profiler -name '*.pyx' -exec cython {} \; # do some edits cd line_profiler && pip install . --user
Installing AUR package from source (PKGBUILD file)
make sure the
base-devel
group is installedsudo pacman -S base-devel
then e.g. for
https://aur.archlinux.org/packages/bluez-utils-compat/
:git clone https://aur.archlinux.org/bluez-utils-compat.git # -s installs build deps, -r uninstalls them after build makepkg -sr # -i installs makepkg -i
other flags you can add to
makepkg -sr
:-A to ignore architecture restriction -c to remove build files after a successful build
bash script: cd to where the script is
cd "${0%/*}"
imagemagick change image white to transparency
mogrify -transparent white image.png
with fuzzy matching:
mogrify -transparent white -fuzz 10% image.png
install packages in octave
e.g. to install
symbolic
:pkg -forge install symbolic pkg load symbolic
add to
~/.octaverc
to load on startup:
tagged: linux commands.md (permalink) (tweet)pkg load symbolic
-
modified March 12, 2021.
Strategy notes for Chu Shogi
update: found this https://web.archive.org/web/20101226050102/http://www.colina.demon.co.uk/books.pdf
chu shogi blogs:
- https://drericsilverman.wordpress.com/2020/04/05/chu-shogi-part-i-how-to-play/
- https://chushogilionhawk.wordpress.com/
chu shogi videos:
- https://www.youtube.com/watch?v=fnJSSd1WCFk
- https://www.bilibili.com/video/BV157411K7nc/
- https://www.youtube.com/watch?v=d245RsjOU64
- https://www.youtube.com/channel/UC0n0caBL4jq8d98QHSpig6A
- https://www.nicovideo.jp/user/3018550/video
I got interested in Chu Shogi (a 12x12 shogi variant) a while back. I was pretty surprised at the lack of strategy-related resources surrounding this game so I decided to write some.
I’m currently running xboard and playing against the HaChu engine. Here’s what I’ve gathered from playing against HaChu 0.21:
Early game
- Early game, the horse is the most powerful piece. Moving the e and h pawns opens up the center diagonals for your horse.
- The e and h pawns are very important. Often you advance them both first to protect the square on 6th rank – if you don’t, the opposing lion can move to those squares in 2 turns and eat your go-betweens. Alternatively you can defend both go-betweens with your lion, but doing this early hurts your setup since it blocks the advance of your center pawns (and the opponent can easily develop while threatening your lion with e.g. horse to j9 or bishop to k10)
- The go-betweens (files d and i) block some very hard-to-move pawns, so you can treat those pawns as walls that will not move ever. So there is a wall between the center and the sides. The go-between is also very hard to move – if you advance the go-between on d5, the opponent can easily move their h pawn (which is a standard opening anyways) and have their horse or bishop threaten c4 and d5.
- After pushing the e and h pawns as well as the copper/silver/leopards on either side, you want to move the side pawns. Make some room by pushing side movers forward
- If the opponent shoves a horse forward early, can usually remove its presence by pushing and sacrificing a horse of your own (if they capture it with the horse, you capture back with bishop)
Early to midgame
- You want to get your bishops out to pressure squares! Do this by moving the horse – either diagonally towards the center or diagonally towards the side. Exposing the left bishop pressures the right side, and vice versa.
- The c, e, h, j pawns are protected by the rook/dragon behind them, no matter how far up they advance. This means they can threaten those files pretty easily – if you sacrifice that pawn, suddenly you have control of the whole file via the rook or dragon. The same goes for the b and k pawns (which hide the vert mover), though those are more often used in side battles.
- A battle on a side is meant to force your opponents to divert resources from the center. The goal is to clean out their b file, at worst you threaten an exchange of vert movers (which you can do whenever you need to force opponent pieces to the side). The basic setup (e.g. for the left side) is to advance the a,b,c pawns once and have a leopard defending all 3 right behind the b pawn. You advance the leopard by moving the side mover up. Alternatively you can have a copper behind the c pawn, which is easier to set up in the case when your horse is out of the way already. If you do this, you can develop your bishop by moving your vert mover down one square (so the leopard defends it) and moving the bishop where it was.
- When do you bring out the lion? Typically I’ve found it makes sense to bring out the lion when you want to apply a lot of pressure on one side of the board. You also want to bring out the lion ASAP if your opponent has brought out the lion.
- Don’t think about capturing the lion until the board is almost clear. Lion chasing puts pressure, sure, but it’s super hard since lion capture rules don’t let you exchange protected lions, and also there are often better moves you can make (like moving your steppers). Lions will almost always survive until endgame.
- You might be tempted to ignore the steppers and only move your flashy powerful pieces (lion, horse, dragon). This is what I did at first, and it let me lock up most of the board. But what happens after the board is locked up and your big pieces are stuck in a standoff with your opponent’s big pieces? That’s where the steppers come in – they’ll step into the standoff and threaten your big pieces, forcing them to move. The player who can advance their steppers sooner, wins the standoff.
- The steppers you don’t want to move are: blind tiger, drunk elephant, and gold general. These will stay behind to protect the king until endgame. The steppers you absolutely want to move (it would be a mistake not to) are: silver general, copper general, ferocious leopard. The phoenix also works as a powerful stepper, as mentioned earlier.
- I find it really hard to make use of pins, since the important pieces are so mobile they won’t put themselves behind a pin. This is less true in the endgame where you’re pinning against the (less mobile) king.
Midgame
- At this point your steppers are all advanced and everything is locked up and you have three pieces defending one pawn that’s being attacked by three pieces, and both lions are watching that pawn.
- Start castling! The Elephant, Tigers, and Golds are the only steppers that can move side-to-side, and are considered perfect for defense because of this.
- The AI always brings out their bishops to control the center, which makes sense since it’s a powerful ranging piece that you also aren’t too afraid to lose. In particular, you use bishops to threaten horses!
- Now that the steppers are here, you can start moving your now-protected go-betweens to add more pressure, and (most importantly) to open up space on the d- and i-files in your camp.
- The free king starts participating to defend big pieces. I’ve also seen the phoenix get brought out onto e4 or i4 (it’s like a long-range stepper). I don’t often see the ki-rin get brought out, it’s just not a very good piece.
- Undoubtedly an exchange happens (or a lion decides to feast) and a bunch of pawns are eaten. Remember the c, e, h, j pawns? Once those are eaten, your rooks and dragons enter the game, and can start wresting control of the middle ranks away from the lion. Don’t be afraid to move your rooks and dragons out, since the side movers should be protecting ranks 3 and 4.
- Now you start pressuring the lion. The rule for checking a lion is simple: putting anything on 8 squares around it often won’t threaten it even if that piece is protected, because the lion can capture without moving (igui). So the best pieces to check the lion with are ranged pieces – this includes the phoenix and ki-rin!
Mid- to endgame
- If you haven’t brought up your steppers by now, bring up your steppers if only to cover all the ground opened by pieces getting captured.
- If you’ve moved your phoenix on g2, consider moving the blind tiger on h2 to g2, to protect that king’s diagonal.
- Now you can start moving your ranged pieces (esp. rooks and dragons) into enemy territory! So you can have the option of capturing, promoting, and then instantly dying since the opponent’s camp is probably still well-protected.
-
modified May 21, 2020.
FP takes on OOP design patterns
tags: pl
Visitor Pattern
Objective: Separate an algorithm from the structure on which it works
In Haskell terms, this means defining an ADT implementing
Functor
. For example:data T a = A | B | C (T a) (T a) deriving Functor
.To call a function
f
on the datamydata
, a client writes:fmap f mydata
(We’ll assume
f
is some unsafe function, since the equivalentvisit
method in Java returnsvoid
.)In Java, the idea is to define an abstract class
Data
, and have some concrete classes that extendData
, e.g.A
,B
,C
. (This is just Java’s way of making an ADT.)Then define an interface called
DataVisitor
defining avisit
method overloaded for argument typesA
,B
, andC
. (This interface is equivalent to defining and implementing aFunctor
typeclass specifically forData
.)Then give each of
A
,B
,C
anaccept
method taking in aDataVisitor
, which does nothing but call theDataVisitor
’svisit
method on itself. (Why define an identicalaccept
method for each ofA
,B
,C
? This is Java’s workaround for pattern matching onData
– having each of its subsclassesA
,B
,C
overload some method.)To call a function
f
on somemydata
, a client needs to do two things. First: define a classFDataVisitor
implementing theDataVisitor
interface, i.e. definingvisit
forA
,B
,C
to do whateverf
does. (Like foraccept
, this is akin to pattern matching on the argument off
, and so you need to define a whole class to givef
that power). Then, the client creates aFDataVisitor
object (call itvisitor
) and writes:mydata.accept(visitor)
In summary, the equivalent bits in the Visitor pattern are:
Java (OOP) Haskell (FP) abstract Data
classADT type A
,B
,C
ADT constructors DataVisitor
interfacespecialized Functor
typeclassvisit
generic f
argument tofmap
accept
fmap
data.accept(f)
fmap f data
FDataVisitor
class and objecta pattern matching branch in f
Interpreter Pattern
Objective: To evaluate an expression in the form of a syntactic tree
In Haskell, this translates to a function (call it
eval
) which performs pattern matching on an ADT. If a local context is needed, it can be encoded by adding an extracontext
argument to the function (which is equivalent to using theReader
monad). A global context can be encoded with theState
monad.In Java, this requires defining an
Expression
interface with aninterpret
method taking in a global context (local context is not possible). Each terminal and nonterminal in the expression grammar is a class implementingExpression
(Java’s way of defining ADTs).Java (OOP) Haskell (FP) Expression
interfaceADT type terminal and nonterminal classes ADT constructors interpret
a pattern matching branch in eval
context extra argument to eval
Command Pattern
Objective: To encapsulate the details of an action to execute it later
In Haskell, each action and its parameters can be encoded as one constructor of an ADT. We can execute it later by writing some
eval
function that pattern matches and does the corresponding command acting on some global state. Since state is often safely encapsulated by stateful monads likeState
orIO
, you might write youreval
in a stateful monad.Alteratively, you can write each action as its own function, and literally store partially-applied functions for later use. This is easier to write and extend, but harder to debug because you can’t print out functions, and because there is no exhaustiveness checking for invalid commands.
In Java, this is the same as Interpreter pattern, except everything is a nonterminal storing some parameters. These nonterminals can be stored, reordered, etc, any way you want (until they are consumed like in the Interpreter Pattern).
Java (OOP) Haskell (FP) Command
interfaceADT type FooCommand
classesADT constructors execute
a pattern matching branch in eval
global state, which commands affect stateful monads Strategy Pattern
To define a family of algorithms which are interchangeable within the family.
In Haskell this means defining various functions (the algorithms) which are all parameterized by the same variables and functions. This can be accomplished by passing along these parameters as an argument, providing them each time you call each function. But the whole point of the Strategy pattern is to avoid having to do that. Avoiding passing arguments all the time is also the whole point of the
State
monad.So, the
State
monad can be used for the Strategy pattern – every function using this strategy will live inState s
wheres
is some ADT holding the aforementioned parameters. To change the strategy, useput
to change the strategy’s variables and functions. Functions using the strategy will useget
to get the strategy’s variables and functions.In Java, this requires our client
Context
object to store somestrategy
member variable implementing theStrategy
interface, which has data and functions used elsewhere in the methods ofContext
. Changing the strategy is as easy as setting thestrategy
member variable.Java (OOP) Haskell (FP) Strategy
interfaces
(ADT for your state)Strategy
objectvalue of type s
family of algorithms the functions living in your State s
monadchanging the Strategy
put
accessing the Strategy
get
methods in Context
your API Adapter Pattern
Objective: To bridge between two incompatible interfaces.
In Haskell, interfaces are typeclasses, so the goal is to let instances of typeclass
Foo
be used as if they are instances of typeclassBar
. We do this by literally implementingBar
for all instances of typeclassFoo
using type variables, likeinstance Foo a => Bar a where ...
which you might read “Foo anything implies Bar anything”. Then instances of typeclass
Foo
can directly be used as if they are instances of typeclassBar
.In Java, this requires writing a
FooAdapter
class which wraps aFoo
but implements theBar
interface. ThenFoo
objects can be used as aBar
objects by wrapping them inFooAdapter
, which is-aBar
.Java (OOP) Haskell (FP) interface typeclass FooAdapter
(unnecessary) wrapper variable in FooAdapter
type variable Iterator Pattern
Objective: To traverse elements of a collection without exposing its underlying representation.
In Haskell, we always write collection-traversing operations as some kind of fold, without exception. So the closest equivalent is the
Foldable
typeclass and its sequentialfoldr
function.In Java, we write this ‘next’ element function by defining a
Iterator
interface with anext
andhasNext
method for traversal. Each collection can define some kind ofcreateIterator
method which returns the correspondingCollectionIterator
class that implementsIterator
.To use this, the client gets an iterator with
createIterator
. Then it enters a loop callinghasNext
to check if the loop continues, andnext
to get the next element in sequence.Java (OOP) Haskell (FP) Iterator
interface(unnecessary) createIterator
(unnecessary) code using Iterator
some kind of fold collection with iterators instance of Foldable
hasNext
whether the pattern match in foldr
is base casenext
use variable from pattern match in foldr
Observer Pattern
Objective: Define a one-to-many relationship between objects such as if one object is modified, it automatically notifies all the depenedent objects.
In Haskell, this is the heart of functional reactive programming (FRP). The gist of it is that updates are
Event
s (a value associated with a time), and states areBehavior
s (values that change depending on time, like a signal in signal theory). Everything is done by modifying and combiningBehavior
s – for example, if it’s true that the engine dies whenever the tank runs out, you’d modify the ‘fuel-in-tank’Behavior
into an engine-is-aliveBehavior
by applying a function(> 0)
, exactly like how it is in signal theory.Whenever updates (
Event
s) happen from the outside, you can turn them intoBehavior
s and use them to change otherBehavior
s. And you can always sample aBehavior
at interesting times to getEvent
s to act on.There isn’t a need to keep track of which objects are subscribed or having to call
update
on each subscribed object, since any potentially interested objects are able to access the state as it exists at every point in time, and are able to define new states from that state based on incoming updates.In Java, the Observer pattern requires a supervising
Subject
class which stores a state (with getter and setter) and a collection ofObserver
objects. It provides anattach
method which adds anObserver
to the collection. The setter for the state must call theupdate
method of eachObserver
with the new state.Observer
is an abstract class with a singleupdate
method. Classes extendingObserver
will defineupdate
to do whatever interesting thing needs to be done on a state change. Whenever anObserver
object is created, it requires a reference toSubject
, so theObserver
constructor can callsubject.attach(this)
in order to add the newObserver
to the watch list.TODO: more patterns
References
- https://blog.ploeh.dk/2017/10/04/from-design-patterns-to-category-theory/
- https://blog.ploeh.dk/2018/08/13/a-visitor-functor/
- https://blog.octo.com/design-patterns-saison-2/
- https://medium.com/@lettier/functional-reactive-programming-a0c7b08f6b67
-
modified April 4, 2020.
CAGED system for guitar
There’s a pattern to memorizing chords up the fretboard pretty quickly as long as you know these basic chord shapes: CAGED
All of the following are C chords: (Start with C)
0 ====== ||||C| ||C||| |C|||| AAAAAA |||||| |||||| 5 GGGGGG ||AAA| |||||| |||||| |G|||| |||||| G||||G EEEEEE |||||| |||E|| 10 DDDDDD |EE||| |||||| |||||| |||D|D CCCCCC ||||D| ||||C| |||||| ||C||| 15 |||||| |C||||
All of the following are F chords: (Start with E and add one fret)
0 ====== EEEEEE |||E|| |EE||| DDDDDD |||||| |||||| 5 CCCCCC |||D|D ||||C| ||||D| ||C||| |||||| |C|||| AAAAAA |||||| |||||| 10 GGGGGG ||AAA| |||||| |||||| |G|||| |||||| G||||G EEEEEE |||||| |||E|| 15 |||||| |EE|||
It’s always in a sequence C A G E D. Try adding two frets instead, it’ll be the same pattern!
CAGED system for guitar (permalink) (tweet)