Sunday, March 13, 2016
Growing Censorship
YouTube music videos that have bad language are replaced with muted versions. And it's not just the F word, it's the word drugs. Popular culture being sanitized, "sucks" being deemed a swear, and not like Kid Rocks words of wisdom "suck my dick" but the widespread general usage, "that sucks". Honestly, today there was an article on WIRED titled, "Dancing in Shackles: Today your Adblock is taking a stand against censorship," and the article made no sense, WIRED blocks content from users using Adblock. Ransoming content for actual money, or forcing ads on the reader that are likely to be the source of the majority of viruses on the net. Censorship of public domain videos, which are becoming clickfarms instead. And no, Amnesty International has no anti-censorship focus going on, you'd have to be a detective to figure out what WIRED is talking about, as far as I can tell Amnesty is collecting donations to promote general human rights, like sexual reproductive freedom, freeing political prisoners and stopping police brutality. If you click on their google ad all you get is a donation form. As for Adblock, it's still blocking ads for now, so for the moment the user still has the power to censor content. It's a never ending struggle though, other people want to decide what you will, can, or must watch.
Saturday, November 9, 2013
Swale Burial
Friday, February 15, 2013
Driving Costs
The average plug-in hybrid driver probably only needs gas 10 times a year or so, or 50 minutes at gas stations in a year. However, they need to plug the car in, which might take a minute or so, and unplug it before they leave, which could take another minute, so over the course of a year there's 12 hours of plugging in and out. There's some experimental "park over" chargers that might help eliminate that, if you take the time to install that... in both your garage floor and in your car. And there is the time for having the plug-in charger installed, though that will no doubt be done by someone else.
So time wise it's about 254 hours for a gas car, and 263 hours for a plug-in electric hybrid car. So it costs 9 hours more, or 3.5% more time to plug-in. The average hourly wage is something like $19.50, though it fluctuates, so overall driving time represents a loss of productivity of around $5,000 per person. $175 more if you drive a plug-in hybrid.
The workforce participation rate is something like 65%, so this $5000 per person represents about $1.17 Trillion in lost productivity. If all workers switch to plug-in hybrids (this isn't likely), the productivity lost will increase to $1.2 Trillion. There's that 3.5% again... so $35 Billion more lost since GDP is something like $15 Trillion that would be only a 0.25% decrease in the GDP. All based on a few minutes plugging in every day.
Friday, January 18, 2013
Large Files (some understandings)
The solution then is just to go ahead and fit all IO into one monolithic call that fits into memory, and write things in pure code like ProcessFile::IO() and ProcessLine :: String -> String and then just map a whole file lazily. In general, since ProcessFile is returned as a single action at the top level, using hGetContents will end up not being all stored in memory unprocessed. There's still some limits here, because ProcessLine might get memoized, and there's no method that I've found yet to just say not to do that.
Tuesday, May 1, 2012
Large Files
Saturday, August 20, 2011
Picnic
Tuesday, February 9, 2010
Killer Cars
Prius brake computers: vroom...splat!
Volvo gas pumps: drip, drip...kaboom!
I wish that car companies weren't in such a hurry to add new features, and that government would stop being so strict on emissions. I had a two door Sunbird in the 80's that got 45 MPG and was sporty, I'm fairly sure the EC had been removed, but it ran clean. I'm sure a Prius isn't getting much better than 50 MPG, probably because of emissions laws. I've heard that a lightweight diesel car with manual transmission and good aerodynamics can get around 100 MPG if you drive it right.
It's the KISS thing, why spend billions redesigning something that already worked fine? Especially if the new one isn't really all that much better.
Wednesday, November 11, 2009
Thursday, August 27, 2009
Politics, Death, and the End of Free Speech
Saturday, July 25, 2009
Haskell Variables
So one of the things that happens is heavier reliance on recursion, the values passed to the function can change like a variable, but they're still parameters. Which leads to encapsulating values in a state monad, and then passing the monadic values around.
What is a monad? That is where most people get very confused. Mathematically a monad is different than how it is implemented in Haskell! In Haskell a monad is really just a data type pointer. So you have something like IO Integer and it's a pointer to an Integer. Unfortunately the IO monad has no good constructor, you need to use IOArray, IORef, TVar or some other monad to create a variable. For now let's stick to using IORef since it's intended for this.
module Main where
import Data.IORef
main = do
-- a new variable called var
var <- newIORef (1::Integer)
-- the contents of var
a <- readIORef var
-- add one to var
modifyIORef var (+1)
-- the contents of var
b <- readIORef var
-- set var to 3
writeIORef var 3
-- the contents of var
c <- readIORef var
putStrLn $ show a
putStrLn $ show b
putStrLn $ show c
This is how variables are done in Haskell, with the following caveat: in general IORef isn't thread safe. So you might rather use something like:
module Variables (Variable, newVar, setVar, getVar, modVar, showVar) where
import Control.Monad
import Control.Concurrent
import Control.Concurrent.STM
type Variable a = TVar a
-- initialize a new variable
newVar :: a -> IO (Variable a)
newVar value = atomically $ newTVar value
-- get the value of a variable
getVar :: Variable a -> IO a
getVar pntr = atomically $ do
value <- readTVar pntr
return value
-- set the value of a variable
setVar :: Variable a -> a -> IO a
setVar pntr value = atomically $ do
writeTVar pntr value
return value
-- apply a function to a variable
modVar :: Variable a -> (a -> a) -> IO a
modVar pntr fn = atomically $ do
value1 <- readTVar pntr
let value2 = fn value1
writeTVar pntr value2
return value2
-- a show function for a variable (for GHCI)
showVar :: (Show a) => Variable a -> IO ()
showVar pntr = do
value <- atomically $ readTVar pntr
putStrLn $ show value
This is thread safe on top of TVar. Variables.hs
So using this we'd have:
module Main where
import Variables
main = do
-- a new variable called var
var <- newVar (1::Integer)
-- the contents of var
a <- getVar var
-- add one to var
modVar var (+1)
-- the contents of var
b <- getVar var
-- set var to 3
setVar var 3
-- the contents of var
c <- getVar var
putStrLn $ show a
putStrLn $ show b
putStrLn $ show c
Which is almost the same as using IORef, but thread safe.
Tuesday, July 7, 2009
Ternary Trees

The basic idea is that a tree consists of branches, leafs, leafy branches, and stubs. Having a leafy branch allows for words to be prefixes of other words, as in the example.
Methods
newTrie a b :: (Ord a) => [a] b -> Trie a b
Create a tree from a single word [a] and associate a value b with it.
insert :: Ord a => [a] -> b -> Trie a b -> Trie a b
Insert a word [a] and a value b into a tree. Insert will return an error if the word already is part of the tree.
lookup :: Ord a => [a] -> Trie a b -> Maybe b
Find the value b associated with a word [a].
map :: (b -> c) -> Trie a b -> Trie a c
Apply a function (b -> c) to all the values b in a tree.
toList :: Ord a => Trie a b -> [([a],b)]
Convert a tree to a list of word-value pairs.
fromList :: Ord a => [([a],b)] -> Trie a b
Convert a list of word-value pairs to a tree.
instance (Binary a, Binary b) => Binary (Trie a b)
An instance of binary for efficient storage of trees. Example: encodeFile "filename" tree
Ternary.hs
Tuesday, May 26, 2009
Haskell Raytracer
Mathematically it's fairly complicated. In general what you do is substitute the formula for a ray into the formula for an object, then find the roots of the resulting equation. So for example if you have a sphere equation:
where Sr is the sphere radius,and the ray equation:

where P is the starting point, and D is the direction.
Then you substitute the ray equation for the XYZ portions:
and then simplify:
Which is in quadratic form, so there's possibly two solutions. Note that if sphereIntersect :: Vector -> Double -> Ray -> Maybe HitOf course you can't end with just spheres, there's planes, boxes, triangles, flat discs, cones, etc.
sphereIntersect loc radius ray@(pnt,dir) =
let pl = pnt - loc
b = 2*((x dir)*(x pl) + (y dir)*(y pl) + (z dir)*(z pl))
c = (x pl)*(x pl) + (y pl)*(y pl) + (z pl)*(z pl) - radius*radius
q = filter (>=epsilon) $ quadRootsIgnoreA b c
in if (q == [])
then Nothing
else let ti = minimum q
iPoint = evaluateRay ray ti
iNorm = (iPoint-loc)/(toVector radius)
in Just (iPoint, iNorm)
Transforms are complex too. Say for example that you'd like to declare a right cone frustum as:
cone {basePnt, baseRad, topPnt, topRad} then you need to rotate and scale the ray along with the cone so that you can test against a standardized cone where you know the formula for the surface: So you end up with pairs of 4x4 matrices describing the transform and it's inverse. Interestingly, once you get a list of transforms to be applied (translate, rotate, scale) they can be composed together into a single transform by matrix multiplication.
The intention is to get this heavy matrix calculation to run once per object, and then use the result transform in testing multiple ray intersects. In Object Oriented languages like C++ this would be done at construction of the object, in Haskell I'd like to partially apply an intersect function, and then use the resulting function on a ray... so: objectFn :: Ray -> Maybe Hit
All that is to be tested and implemented still.
Currently I'm working on torus, a torus-ray intersect results in a quartic equation:
Thursday, February 26, 2009
TomTom sued by Microsoft
This is the sort of thing that has driven the economy into the second great depression. If the legal system continues to extort money in this manner then civilization may collapse.
Wednesday, February 4, 2009
Vista
Thus began the Vista woes, the Lexmark 3-in-1 printer isn't at all supported in Vista, and Lexmark basically is thumbing it's nose at customers, you can't get a Linux driver for it, you can't get a Vista driver, it might as well be a paperweight. Then re-installing programs has come up with dozens of paranoia firewall dialogs for each install. More startling, it's actually stalled the processor a few times... it's an AMD 1.8g quad core, so far I can't see much performance improvement from the old 1.8g Athlon. Thank goodness for backups, but all the registry is different, so it's password and number hunt week.
Tuesday, December 30, 2008
Plastic Welder
Sunday, November 9, 2008
Vectorizing
It kept bugging me that my Voronoi code didn't return anything but an image to double check, so I figured a way to go ahead and make it output SVG format paths. I also added some routines to help further simplify the paths, though the output still seems a bit rough. And it was a good thing to check my results, because the simple lengthening of segments somehow resulted in gaps in the path, the sort of thing that would ruin a circuit board. For now I just commented that part out and substituted code that checks if a line is trending in a direction, and then double checked against the error (measured as the sum of the distances from the proposed line to the pixels that would be removed).
I suppose that using Haskell for this might seem like an odd choice, but I'm more familiar with it than Python. The SVG image in this post should show up fine in Firefox. If your browser has trouble with it I'm sure you can Google around an get SVGs to display.
Vornoi.hs
Monday, October 27, 2008
Voronoi
After seeing Forrest Higgs working on using Voronoi isolates (a version of a Voronoi diagram that starts with lines instead of points) I was inspired to write a similar program which turned out well. The basic algorithm is to expand pixels around a color coded line until it meets another color. If a pixel is neighboring more than one color it gets painted black, rinse and repeat until there's nothing white left.It was a bit of a struggle to get PNG images edited in Haskell, but eventually I realized that pixbufGetPixels isn't really returning an array, it's returning an array typed pointer to a pixBuf. This makes sense in a practical memory usage way, but it isn't what I expected from the context.
After that I vectorized the edges, that took quite a bit of thought. First line segments were created between the centers of adjacent black pixels, then segments were created from the center of black pixels to any corner of the black pixel where there was a color change between neighboring pixels, and lastly segments between differing colors. This left a bunch of empty sets, and repeated segments, which were filtered out. That resulted in about 4400 segments for this test image. The next step is to lengthen vectors that are near each other in the same directions. That reduced the number of segments for this test to about 3700, it probably could be much fewer if I hadn't limited the angles (0, 45, 90, and 135) or if the underlying lines were horizontal, vertical, and perfectly diagonal.
For now I can't go much farther without hardware to test on...
Voronoi.hs
Sunday, September 28, 2008
X Axis
I also trimmed some plastic from the bed near the end to make clearance for the motor to be mounted to a threaded rod. There is a small tendency of the carriage to ride up out of it's slot, but when the rod is attached that will act to keep it from riding up. The profile of the rail should not matter much. The same setup should work fine with metal rod, pipe, angle iron, etc. Any profile where you have a straight inner surface, and a straight top surface.
Monday, September 8, 2008
Boxer Fan
I found a fan that looks a lot like a computer fan, but it's 110V and bigger. It was seized, so I removed the center from the bearings by persuading it with a hammer and a set. That released the blades and rotor. I cleaned away all the corrosion with emery paper, and sprayed it well with WD40. The bearings were still fine, so after pressing it back together the blades spun freely. I soldered a power cord to it and it runs OK; it's not too loud. I also rubber banded a 45 Gallon garbage bag to it to get an idea of the airflow, it filled the bag in five or six seconds, so it's probably about 60 cubic feet per minute.
Tuesday, September 2, 2008
Cooking with gas
I melted some more HDPE, this time I did it in the garage on a gasoline burner. I wrapped the plastic in aluminum foil to keep it from sticking to the pan. Then I squashed it flat between two pans and left some heavy chain on it while it cooled. I ended up with a 1/4" x 8" cookie of plastic sheet, it's mostly flat, and the foil is well stuck to it. I'm not sure what I'll use it for. Mostly I've just been cleaning and storing stuff from the pile. My second computer won't boot any more, it sat too long, or it needs a battery, and the power supply was always extra noisy, it locks part way through boot up usually. I wonder if this was related to the ethernet problem I had last month, even though that computer is off most the time. All the time now I guess, maybe I'll get a couple new power supplies, and try one in that. I need another computer for the garage anyways, so I can do the RepRap stuff there.

