let it leave me like a long breath

let it dissipate or fade in the background

Entries tagged with programming

Profile

xax: purple-orange {11/3 knotwork star, pointed down (Default)
howling howling howling

Nav

  • Recent Entries
  • Archive
  • Reading
  • Tags
  • Memories
  • Profile

Tags

  • art - 2 uses
  • asteroid garden - 4 uses
  • code - 19 uses
  • demos - 1 use
  • dreams - 5 uses
  • ff7 fangame - 23 uses
  • fic prompts - 13 uses
  • gamedev challenge - 82 uses
  • hell game - 76 uses
  • nanowrimo - 11 uses
  • plants - 9 uses
  • process - 52 uses
  • programming - 51 uses
  • screenshots - 5 uses
  • writing log - 83 uses

May 2025

S M T W T F S
    123
45678 910
1112131415 1617
18192021222324
25262728293031
    • Next 20
  • Nov. 6th, 2015
  • xax: purple-orange {11/3 knotwork star, pointed down (Default)
    • Current Music: Fall Out Boy - Immortals
    Tags:
    • programming
    posted @ 05:40 pm

    this coding game has a text parsing-and-formatting problem & it's in the "hard" category

    but the haskell packages they have include: parsec (which i guess is actually in base?? haskell's base is so weird)

    so, i guess i know what i'm gonna do!!

    update: solved it and got 100%, hooray. biggest issue was just making sure to insert spaces basically everywhere.

    • Add Memory
    • Share This Entry
    • Link
    • 0 comments
    • Reply
  • Nov. 4th, 2015
  • xax: purple-orange {11/3 knotwork star, pointed down (Default)
    Tags:
    • programming
    posted @ 01:14 pm

    also i've been playing ("playing") some programming game website. it is weird b/c it's half about NETWORKING and BUILDING A PORTFOLIO; there are challenges ingame that are like "and then when you pass this yr code will be forwarded to the people at {corporation} who might extend a job offer to you!!". you have to qualify to look at ads b/c those ads are IMPORTANT PROGRAMMING JOBS YOU QUALIFY FOR BASED ON YR PROGRESS INGAME!! gamifying looking for work; it's kind of grotesque.

    anyway here's my profile. a lot of these problems are v. easy using haskell; i tried solving one in c and it immediately reminded me of why i stopped using c once i started using haskell.

    i think it's weird how like two days of writing code took me to the top 5% and then another two days of writing slightly more complex code took me to the top 2%. it's like, is this because i am in fact Good At Programming? or just that the site doesn't hook most users? (i tried a 'shortest source' challenge and got 3 pts b/c i am real bad at that, and that still puts me in the top 3% since presumably 97% of accounts have precisely 0 pts in optimization)

    ACHIEVEMENTS! STATISTICS! QUANTIFICATION!!!

    • Add Memory
    • Share This Entry
    • Link
    • 0 comments
    • Reply
  • Oct. 27th, 2015
  • xax: purple-orange {11/3 knotwork star, pointed down (Default)
    • Current Music: The Mountain Goats - Palmcorder Yajna
    Tags:
    • code,
    • programming
    posted @ 01:07 pm

    appl1 :: (a -> t) -> a -> t
    appl1 = id
    appl2 :: (a -> b -> t) -> (a, b) -> t
    appl2 f (a, b) = appl1 (f a) b
    appl3 :: (a -> b -> c -> t) -> (a, (b, c)) -> t
    appl3 f (a, b) = appl2 (f a) b
    appl4 :: (a -> b -> c -> d -> t) -> (a, (b, (c, d))) -> t
    appl4 f (a, b) = appl3 (f a) b
    appl5 f (a, b) = appl4 (f a) b
    appl6 f (a, b) = appl5 (f a) b
    -- etc
    
    appr1 :: (a -> t) -> a -> t
    appr1 = id
    appr2 :: (a -> b -> t) -> (b, a) -> t
    appr2 f (n, rs) = appr1 f rs n
    appr3 :: (a -> b -> c -> t) -> (c, (b, a)) -> t
    appr3 f (n, rs) = appr2 f rs n
    appr4 :: (a -> b -> c -> d -> t) -> (d, (c, (b, a))) -> t
    appr4 f (n, rs) = appr3 f rs n
    appr5 f (n, rs) = appr4 f rs n
    appr6 f (n, rs) = appr5 f rs n
    -- etc

    this can be somewhat generalized so we're not stuck using only tuples forever (this is with viewpatterns btw):

    class Splittable a b c | a -> b c where
    	_fst :: a -> b
    	_snd :: a -> c
    
    instance Splittable (a, b) a b where
    	_fst = fst
    	_snd = snd
    
    pair :: Splittable a b c => a -> (b, c)
    pair a = (_fst a, _snd a)
    
    applg1 :: (a -> t) -> a -> t
    applg1 = id
    applg2 :: Splittable s a b => (a -> b -> t) -> s -> t
    applg2 f (pair -> (a, b)) = applg1 (f a) b
    applg3 :: (Splittable s a s', Splittable s' b c) => (a -> b -> c -> t) -> s -> t
    applg3 f (pair -> (a, b)) = applg2 (f a) b
    applg4 f (pair -> (a, b)) = applg3 (f a) b
    applg5 f (pair -> (a, b)) = applg4 (f a) b
    applg6 f (pair -> (a, b)) = applg5 (f a) b
    
    apprg1 :: (a -> t) -> a -> t
    apprg1 = id
    apprg2 :: Splittable s a b => (b -> a -> t) -> s -> t
    apprg2 f (pair -> (n, rs)) = apprg1 f rs n
    apprg3 :: (Splittable s a s', Splittable s' b c) => (c -> b -> a -> t) -> s -> t
    apprg3 f (pair -> (n, rs)) = apprg2 f rs n
    apprg4 f (pair -> (n, rs)) = apprg3 f rs n
    apprg5 f (pair -> (n, rs)) = apprg4 f rs n
    apprg6 f (pair -> (n, rs)) = apprg5 f rs n


    but what i'd really like is to generalize these functions so that i don't need an infinite number of them based off of their argument count. they all do the same thing!! given what i've read about polyvariadic functions in haskell this should be totally possible. i just haven't really wrapped my head around the code yet.

    and also maybe some way to set it up so the function type there doesn't have to be a function? like the only function i really want to get out of this whole deal is something like render :: (Extend (Extend (Extend ...) v') v) -> (... ? v' ? v -> t) -> Map k t except i can't even come close to formulating what that type would look like. especially given Extend isn't a type but instead a typeclass.

    • Add Memory
    • Share This Entry
    • Link
    • 0 comments
    • Reply
  • Oct. 22nd, 2015
  • xax: purple-orange {11/3 knotwork star, pointed down (Default)
    • Current Music: Panic! At The Disco - Hallelujah
    Tags:
    • programming
    posted @ 06:15 pm

    so i split this problem into "pure structure" and "pure generation" parts, and now that the structure half is basically finished (well, has its first draft working), uh, i kinda have to... make some generation to put into it. which is difficult b/c i still don't have a whole lot in the way of generation algorithms. whoops.

    i guess now would be the time to try and work out voronoi cell code in haskell, since no one seems to have gotten to it before me. or just throw some junk at the wall and see what sticks.

    • Add Memory
    • Share This Entry
    • Link
    • 0 comments
    • Reply
  • Oct. 21st, 2015
  • xax: purple-orange {11/3 knotwork star, pointed down (Default)
    • Current Music: Groove Armada - Paper Romance (Softwar Remix)
    Tags:
    • code,
    • programming
    posted @ 08:34 pm

    "we believe in rough consensus and running code"

    here's some running code i wrote, which i share to inspire you all: ( Read more... )

    • Add Memory
    • Share This Entry
    • Link
    • 0 comments
    • Reply
  • Oct. 18th, 2015
  • xax: purple-orange {11/3 knotwork star, pointed down (Default)
    • Current Music: toby fox - You Idiot
    Tags:
    • programming
    posted @ 11:55 am

    instance (Ord k, Monad m, Generator a m k u) => Generator (Layer a u m k v) m k v where


    yes, this is fine. this type signature is totally okay.

    • Add Memory
    • Share This Entry
    • Link
    • 0 comments
    • Reply
  • Oct. 13th, 2015
  • xax: purple-orange {11/3 knotwork star, pointed down (Default)
    • Current Music: Coheed and Cambria - The Willing Well I: Fuel for the Feeding End
    Tags:
    • programming
    posted @ 07:18 pm

    tiltRandomly :: (a, a) -> Plane a -> Rand g (Plane a)
    tiltRandomly (lo, hi) p =
      if (lo > hi)
        then error "tiltRandomly: lo > hi"
        else case (listToMaybe . liftM catMaybes . sequence . repeat $ do
          v <- V2 <$> randomR (0, hi) <*> randomR (0, hi)
          if magnitude v <= hi && magnitude v >= lo
            then $ Just v
            else Nothing) of
          Just v -> return $ tilt v p
          Nothing -> error "tiltRandomly: uh wow that infinite list sure evaluated fast huh"
    
    

    i think this is the first time i've explicitly used laziness to my advantage

    but of course it's in a messy partial function. also, bad news if you set lo & hi such that it takes like eight million tries to get a value that passes! laziness sure is a thing.


    • Add Memory
    • Share This Entry
    • Link
    • 0 comments
    • Reply
  • Sep. 9th, 2015
  • xax: purple-orange {11/3 knotwork star, pointed down (Default)
    Tags:
    • programming
    posted @ 01:23 pm

    obligatory monad tutorial

    so i wrote basically one good, general-purpose Haskell Code post on tumblr, so i figured i could fix it up a little and post it over here too. it is i guess somewhat monad tutorial fallacy-y, but it's not really about monads.

    it's about the applicative hierarchy! this is a set of three typeclasses: Functor, Applicative, and Monad, in that order. each of these typeclasses has a lifting function, and all but Functor have a unit function.

    (the unit function is a -> f a, so just something that takes an existing value and places it inside the functor. it's called pure in Applicative and return in Monad. specific Functors will generally have ways to put values inside them, of course -- List has : and Maybe has Just, for example -- but they're not considered essential to the typeclass as they are in Applicative or Monad. this is i think a quirk of haskell's history, and not really anything reflective of underlying category-theory gibberish.)

    • Functor's lifting function is Functor f => (a -> b) -> f a -> f b and is called fmap
    • Applicative's lifting function is Applicative f => f (a -> b) -> f a -> f b and is called <*> or ap
    • Monad's lifting function is Monad f => (a -> f b) -> f a -> f b and is called =<< or bind

    the big takeaway here is that you can (and should) think of these as variations on a theme: assuming you want a function f a -> f b, each one takes one function of varying power and turns it into a function across values of your functor.

    it is like you are saying "hey, i want a f a -> f b function, but i don't really want to write all that context-handling code myself. isn't there an easier way?" and it turns out that there can be, if you don't actually care that much about the context!

    the reason why this is a "hierarchy" rather than just being three typeclasses each doing a similar thing is that each of these classes is strictly more powerful than the ones that come before it, in a very precise sense: using each class's lifting function, you can recreate the lifting functions of the lower classes.

    • fmap can be said in Applicative as (<*>) . pure
    • <*> can be said in Monad as \mf mv -> (\f -> (\v -> return $ f v) =<< mv) =<< mf (there are more concise, less readable ways to put that)

    practical applications:

    • like it says, fmap only cares about the values in the functor, not the context itself. if you just want to change the values inside the functor, this is the lifting function to use. since this doesn't alter the functor context, there's generally a pretty clear correspondance between values before and after the function application (the values in a list will remain in the same order, for example)
    • <*> is useful when you have a function that, itself, is inside a functor context. what this does is uses the functor context to inform the functor context and the value context to inform the values -- there's no crosstalk allowed: if you have Maybe a and Maybe (a -> b), the functor context depends entirely on whether they're both Just, and not at all on the actual values. and the values depend entirely on the function, and not at all on the functor context. having a function inside a context might not seem like a common occurance, but the big use is multi-argument functions. fmap is all well and good when you have a one argument function of the form a -> b, but if you try to fmap something with a type signature of a -> b -> c things get messy. you end up with something like f (b -> c), which is basically useless in Functor. except then <*> comes along and lets you transform that into a function f b -> f c, which is wayyy more useful. this works indefinitely, for as many arguments as you want -- fmap works on 1-argument functions, but fmap plus <*> works on n-argument functions. (fmap with an Applicative constraint is called <$>, and you usually see it in places like (*) <$> [1,2,3] <*> [4,5,6], or to construct a type with a constructor when your values are all inside some Applicative)
    • =<< is useful when you care a little about the output functor context. maybe you're looking up values from a table, so you might want to have a Maybe a value on output. maybe you're splitting things into lists, so you want to have a [a] value on output. and then it turns out you're also using Maybe or [] values on input! using fmap would get you something like Maybe (Maybe a)) or [[a]], and you don't care about that extra layer of depth. On lists, =<< is a lot like \f -> concat . fmap f

    some examples:

    > fmap (* 2) [1..10]
    [2,4,6,8,10,12,14,16,18,20]

    the input and output lists are the same length: fmap is incapable of changing "functor context", which here means "list length".

    > [(* 2), (+ 1)] <*> [1..10]
    [2,4,6,8,10,12,14,16,18,20,2,3,4,5,6,7,8,9,10,11]

    and here we see that the Applicative "context" for lists says to treat them like cartesian joins: each list item is applied to each list item in the other list. so we can alter the "functor context" (read: list length) of the result, but only in ways that naturally follow from the functor context of the arguments. in this case, 2 items * 10 items = 20 items.

    > (\x -> replicate x x) =<< [1..10]
    [1,2,2,3,3,3,4,4,4,4,5,5,5,5,5,6,6,6,6,6,6,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10]

    and here, since we're creating a new "functor context", we can make the resulting list any length we want.


    some minutiae:

    • this is why the Functor-Applicative-Monad proposal exists, btw. when haskell came around, first there was Functor, and then there was Monad. it was only later that people realized Applicative was there and was useful, and so we ended up in this situation where instancing something to Monad required a Functor instance, but not an Applicative, despite every Monad also being an Applicative.
    • i've been lying about bind: in haskell, bind is >>=, which has the arguments the other way around (so, f a -> (a -> f b) -> f b); i feel like this obscures the actual properties of the bind operation and so for that and other reasons i tend to use =<< instead. in practice, =<< composes "backwards", in that you have to read it from right-to-left to figure out how a value is transformed. to me, that's fine -- that's also the way function composition works, and it's better to always read right-to-left than to switch back and forth depending on whether you're using monads or not. but the do-notation uses >>= because it gets a left-to-right, top-to-bottom reading, and a lot of people use >>= generally for the same reason.
    • each typeclass has renamed versions of the lower functions, just with different constraints. i already mentioned Applicative's version of fmap, <$>. Monad has liftM for fmap and ap for <*>. generally it's considered good practice to use whichever version carries the least constraints. if you only need to fmap something, it's preferred to just use fmap instead of liftM, unless you're already working under a Monad f => constraint
    • everyone talks a lot about the IO monad, because that's the monad that gets the most use, and is the one everyone has to deal with first. IO is deeply magical for reasons i'm not going to get into, and that most 'monad tutorials' cover. Monad is just a typeclass, like any other typeclass, and it can be understood generally. in general one can only operate on a monadic value inside monadic code, but a lot of the time you can do things like pattern-match on a constructor, or use functions like fromMaybe to pull "monadic" values out into the rest of your code to, in essence, get a m a -> a function. this is fine. but not all monads let you do it; this depends less on "monads" and more on the specific type you're using (that happens to have a Monad instance)

    • Add Memory
    • Share This Entry
    • Link
    • 0 comments
    • Reply
  • Sep. 6th, 2015
  • xax: purple-orange {11/3 knotwork star, pointed down (Default)
    • Current Music: The Mountain Goats - The Diaz Brothers
    Tags:
    • code,
    • programming
    posted @ 04:04 pm

    data BSPControl f a n e = BSPControl
      { minSize :: a
      , maxGeneration :: Integer
      , splitRange :: (Float, Float)
      , divideControl :: Maybe (f a -> f a -> Integer -> Bool)
      , includeSmallOverlaps :: Bool
      , rebuild :: f a -> f a -> n
      , reconnect :: f (TouchState a) -> e
      }
    
    delve :: (Graph gr, RandomGen g, Random a, Integral a, Ord a, Num (f a), Applicative f, Metric f, Traversable f) => BSPControl f a n e -> f a -> Rand g (gr n e)
    delve c size = liftM (construct c) $ bsp c size

    so this is dimension-agnostic binary-space-partitioning code, which is nice, but wow are those a lot of type constraints. for a while i had both Integral a and Floating a constraints, which basically meant that there was no possible type that could work with the code. i'd still like to get rid of that Integral requirement, since it only comes up once in the entire set of functions, and there it's just because i need something i can cast to and from a floating-point value.

    (the f values are expected to be V* values from Linear)

    the bit that was most confusing at first (how exactly do i determine if n-dimensional axis-aligned prisms are touching) ended up being radically simplified due to Applicatives:

    touching :: (Applicative f, Foldable f, Ord a, Num a) => BSPRoom (f a) -> BSPRoom (f a) -> f (TouchState a)
    touching (BSPRoom pos size _) (BSPRoom pos' size' _) =
      test <$> pos <*> size <*> pos' <*> size'
      where
        test :: (Ord a, Num a) => a -> a -> a -> a -> TouchState a
        test start1 length1 start2 length2 = if start2 < start1
          then test start2 length2 start1 length1
          else case min length2 (start1 + length1 - start2) of
            x | x < 0 -> NoContact
              | x == 0 -> Touching start2
              | otherwise -> Overlapping start2 x

    since of course if you have axis-aligned prisms you can decompose each of the dimensionality tests, so what this ends up doing is generating a vector that contains contact information for each dimension, and it turns out there are pretty simple rules for figuring out just when a contact vector is "really" touching, which i will LEAVE DETERMINING AS AN EXERCISE FOR THE READER. (hint: all dimensions being Touching means the two things touch on a single point; all dimensions being Overlapping means the two things contain a full overlapping subprism.) sadly i haven't really figured out a way to type-agnostically transform that into something useful (e.g., planes or lines) but whatever, the type variables have gotta run out sometime.


    • Add Memory
    • Share This Entry
    • Link
    • 0 comments
    • Reply
  • Aug. 31st, 2015
  • xax: purple-orange {11/3 knotwork star, pointed down (Default)
    • Current Music: Jai Paul - BTSTU
    Tags:
    • programming
    posted @ 09:24 pm

    yeahhhhhhh i finally dug into the weird, confusing guts of Linear.Metric and Linear.Vector and wrote a dimension-agnostic version of the bsp code! so now i can just take all my 2d maps and be like "actually do this in 3d instead" and it will Just Work. (i could also do it in 1d or 4d but those seem less useful)

    uhhh up next though: doing the same for all the other generation code.

    i read a lot of A PATTERN LANGUAGE this morning and it kind of rubbed off on me. i wanna generate some buildings. christopher alexander's aesthetic is almost painfully bucolic, though.

    • Add Memory
    • Share This Entry
    • Link
    • 0 comments
    • Reply
  • Aug. 10th, 2015
  • xax: purple-orange {11/3 knotwork star, pointed down (Default)
    Tags:
    • programming
    posted @ 12:54 pm

    actually in programming news

    so my rhombic-dodecahedral setup has come a ways since i last posted a bunch of screenshots, which is neat, but increasingly it's like... it runs into the same problem as minecraft, which is that the world cell size is large enough and rigid enough that it's impossible to do subtle detail. this has kind of been a problem w/ the setup from day one, and i have yet to figure out a good resolution to that problem. like the first draft was adding lines between any grid vertices and then drawing polygons on top of those, which would... help, but idk it doesn't really seem sufficient unless the generated world geometry is mostly lines and polygons instead of just cells.

    soooooo i've been dwelling on that some recently, and still not really coming up with any good solutions. probably i should keep digging at my random-generation code and see what i can add, since once i start generating more visually-complex areas that might give me a better idea of just what i need to add.

    • Add Memory
    • Share This Entry
    • Link
    • 0 comments
    • Reply

Syndicate

RSS Atom
Page generated Aug. 21st, 2025 10:22 pm
Powered by Dreamwidth Studios

Style Credit

  • Style: (No Theme) for vertical