• 22 Posts
  • 120 Comments
Joined 2 years ago
cake
Cake day: May 9th, 2024

help-circle
  • Futhark + sed

    Futhark can read only number and array types from stdin, the input data is often a non-starter. Therefore, I often massage it into the right format using sed.

    Sed Script
    s/[: ]/,/g
    s/[rgbs]/0/g
    s/[RGBS]/1/g
    1s/^/[ [/
    2,$s/^/, [/
    s/$/]/
    s/,\([01]\)/,0b\1/g
    
    $a]
    

    This formats everything nicely, e.g. the example for part 1:

    2456:rrrrrr ggGgGG bbbbBB
    7689:rrRrrr ggGggg bbbBBB
    3145:rrRrRr gggGgg bbbbBB
    6710:rrrRRr ggGGGg bbBBbB
    

    is transformed into this:

    [ [2456,0b000000,0b001011,0b000011]
    , [7689,0b001000,0b001000,0b000111]
    , [3145,0b001010,0b000100,0b000011]
    , [6710,0b000110,0b001110,0b001101]
    ]
    
    Futhark Solution
    entry part1 (colors: [][4]i32) =
      let isGreenDominant c = c.g > c.r && c.g > c.b
      in colors
         |> map (\array -> (array[0], {r = array[1], g = array[2], b = array[3]}))
         |> filter ((.1) >-> isGreenDominant)
         |> map (.0)
         |> i32.sum
    
    type Optional 'a = #absent | #present a
    
    def map_optional 'a 'b (f: a -> b) (this: Optional a) : Optional b =
      match this
      case #absent -> #absent
      case #present a -> #present (f a)
    
    def optional_is_present 'a (this: Optional a) : bool =
      match this
      case #absent -> false
      case _ -> true
    
    def unwrap_optional 'a (this: Optional a) : a =
      match this
      case #absent -> assert (("unwrap_optional: #absent", false).1) ([][1])
      case #present a -> a
    
    def bind_optional 'a 'b (f: a -> Optional b) (this: Optional a) : Optional b =
      match this
      case #absent -> #absent
      case #present a -> f a
    
    def maximum_by 'a (gte: a -> a -> bool) (as: []a) : Optional a =
      let choose (this: Optional a) (other: Optional a) =
        match (this, other)
        case (#absent, o) -> o
        case (t, #absent) -> t
        case (#present t, #present o) -> #present (if o `gte` t then o else t)
      in reduce choose #absent (map (\a -> #present a) as)
    
    type ShineColor = {r: i32, g: i32, b: i32, s: i32}
    
    def array2ShineColor (array: [5]i32) : (i32, ShineColor) = (array[0], {r = array[1], g = array[2], b = array[3], s = array[4]})
    
    def on f g a b = f (g a) (g b)
    
    entry part2 (colors: [][5]i32) =
      let gte (this: ShineColor) (other: ShineColor): bool =
        let colorSum c = c.r + c.g + c.b
        in this.s > other.s || (this.s == other.s && colorSum this <= colorSum other)
      in colors
         |> map array2ShineColor
         |> maximum_by (gte `on` (.1))
         |> unwrap_optional
         |> (.0)
    
    type Shininess = #matte | #shiny
    type DominantColor = #red | #green | #blue
    
    def filterMap 'a 'b [n] (f: a -> Optional b) (as: [n]a) : []b =
      as
      |> map f
      |> filter optional_is_present
      |> map unwrap_optional
    
    def categorize_shininess (s: i32) : Optional Shininess =
      if s <= 30 then #present #matte else if s >= 33 then #present #shiny else #absent
    
    def categorize_color (color: ShineColor) : Optional DominantColor =
      if color.r > color.g && color.r > color.b
      then #present #red
      else if color.g > color.r && color.g > color.b
      then #present #green
      else if color.b > color.r && color.b > color.g
      then #present #blue
      else #absent
    
    def categorize ((value, color): (i32, ShineColor)) : Optional (i32, (DominantColor, Shininess)) =
      categorize_shininess color.s
      |> bind_optional (\s -> map_optional (\c -> (c, s)) (categorize_color color))
      |> map_optional (\g -> (value, g))
    
    -- >>> category_index (#red, #shiny)
    -- 3
    
    def category_index ((c, s): (DominantColor, Shininess)) : i64 =
      (+) (match c
           case #red -> 0
           case #green -> 1
           case #blue ->
             2)
          (match s
           case #matte -> 0
           case #shiny -> 3)
    
    def (&&&) f g x = (f x, g x)
    def sum2d (a, b) (c, d) : (i32, i32) = (a + c, b + d)
    
    entry part3 (colors: [][5]i32) =
      colors
      |> map array2ShineColor
      |> filterMap categorize
      |> map ((.1) >-> category_index &&& ((.0) &&& const 1))
      |> unzip
      |> uncurry (hist sum2d (0, 0) 6)
      |> maximum_by ((>=) `on` (.1))
      |> unwrap_optional
      |> (.0)
    

    I had hoped that the input might get big enough for optimization purposes, but the calculations are likely too simple.






















  • Quite an in-depth answer, more than I had hoped for.

    I agree with your first point, though I feel obliged to point out that I would not have asked this question anywhere if the focus had been whether cisgender people encourage the usage of two gender stereotypes.

    I think we already agree on the second point. I had hoped to bring that across with the following section:

    I think these prejudices are actively harmful to non-conforming people, since they may be perceived as socially inept or weird (consider young adults/school).

    My writing must’ve been to imprecise, sorry about the confusion. If you feel that I’ve misunderstood the point you made, please elaborate or try a different wording so that I may try again.

    I cannot challenge your third point and will accept it on the basis that you have more experience and knowledge on the topic.

    It’s always easy to clarify something after the fact (“I didn’t mean it that way”), but here I go.

    It’s not my intention to vilify or blame trans people, whom you rightfully defend. I crafted this question with my mind set on the following: “If I were trans, would I be supporting gender stereotypes and/or how to avoid it”.

    Not sure where you read me blaming trans people for their own mistreatment, I will probably not add clarifications to the post since it might undermine the authenticity of your response.