• 0 Posts
  • 41 Comments
Joined 1 year ago
cake
Cake day: June 11th, 2023

help-circle
  • J

    Didn’t try to make it clever at all, so it’s fairly slow (minutes, not seconds). Maybe rewriting foldl_ops in terms of destructive array update would improve matters, but the biggest problem is that I don’t skip unnecessary calculations (because we’ve already found a match or already reached too big a number). This is concise and follows clearly from the definitions, however.

    data_file_name =: '7.data
    lines =: cutopen fread data_file_name
    NB. parse_line yields a boxed vector of length 2, target ; operands
    NB. &. is "under": u &. v is v^:_1 @: u @: v with right rank of v
    parse_line =: monad : '(". &. >) (>y) ({.~ ; (}.~ >:)) '':'' i.~ >y'
    NB. m foldl_ops n left folds n by the string of binary operators named by m,
    NB. as indices into the global operators, the leftmost element of m naming
    NB. an operator between the leftmost two elements of n. #m must be #n - 1.
    foldl_ops =: dyad define
       if. 1 >: # y do. {. y else.
          (}. x) foldl_ops (((operators @. ({. x))/ 2 {. y) , 2 }. y)
       end.
    )
    NB. b digit_strings n enumerates i.b^n as right justified digit strings
    digit_strings =: dyad : '(y # x) #:"1 0 i. x ^ y'
    feasible =: dyad define
       operators =: x  NB. global
       'target operands' =. y
       +./ target = ((# operators) digit_strings (<: # operands)) foldl_ops"1 operands
    )
    compute =: monad : '+/ ((> @: {.) * (y & feasible))"1 parse_line"0 lines'
    result1 =: compute +`*
    
    concat =: , &.: (10 & #.^:_1)
    result2 =: compute +`*`concat
    
    

  • J

    Today’s the first one where I feel like the choice of language is a disadvantage without compensating advantages. Or, at least, I don’t know J well enough yet to use its compensating advantages for this kind of task, so what I end up with is Python 2 with obscure syntax and no associative data structures.

    Also, I can’t post my code, because apparently Lemmy is interpreting some of today’s bizarre line noise as hostile and sanitizing it. It looks more or less like the other imperative solutions here, just with more punctuation.


  • J

    This is a problem where J’s biases lead one to a very different solution from most of the others. The natural representation of a directed graph in J is an adjacency matrix, and sorting is specified in terms of a permutation to apply rather than in terms of a comparator: x /: y (respectively x \: y) determines the permutation that would put y in ascending (descending) order, then applies that permutation to x.

    data_file_name =: '5.data'
    lines =: cutopen fread data_file_name
    NB. manuals start with the first line where the index of a comma is < 5
    start_of_manuals =: 1 i.~ 5 > ',' i.~"1 > lines
    NB. ". can't parse the | so replace it with a space
    edges =: ". (' ' & (2}))"1 > start_of_manuals {. lines
    NB. don't unbox and parse yet because they aren't all the same length
    manuals =: start_of_manuals }. lines
    max_page =: >./ , edges
    NB. adjacency matrix of the page partial ordering; e.i. makes identity matrix
    adjacency =: 1 (< edges)} e. i. >: max_page
    NB. ordered line is true if line is ordered according to the adjacency matrix
    ordered =: monad define
       pages =. ". > y
       NB. index pairs 0 <: i < j < n; box and raze to avoid array fill
       page_pairs =. ; (< @: (,~"0 i.)"0) i. # pages
       */ adjacency {~ <"1 pages {~ page_pairs
    )
    midpoint =: ({~ (<. @: -: @: #)) @: ". @: >
    result1 =: +/ (ordered"0 * midpoint"0) manuals
    
    NB. toposort line yields the pages of line topologically sorted by adjacency
    NB. this is *not* a general topological sort but works for our restricted case:
    NB. we know that each individual manual will be totally ordered
    toposort =: monad define
       pages =. ". > y
       NB. for each page, count the pages which come after it, then sort descending
       pages \: +/"1 adjacency {~ <"1 pages ,"0/ pages
    )
    NB. midpoint2 doesn't parse, but does remove trailing zeroes
    midpoint2 =: ({~ (<. @: -: @: #)) @: ({.~ (i. & 0))
    result2 =: +/ (1 - ordered"0 manuals) * midpoint2"1 toposort"0 manuals
    


  • J

    Unsurprisingly this is the kind of problem that J is really good at. The dyadic case (table) of the adverb / is doing all the heavy lifting here: it makes a higher rank tensor by traversing items of the specified rank on each side and combining them according to the remaining frame of each side’s shape. The hard part is arranging the arguments so that your resulting matrix has its axes in the correct order.

    data_file_name =: '4.data'
    
    NB. cutopen yields boxed lines, so unbox them and ravel items to make a letter matrix
    grid =: ,. > cutopen fread data_file_name
    NB. pad the grid on every side with #'XMAS' - 1 spaces
    hpadded_grid =: (('   ' & ,) @: (, & '   '))"1 grid
    padded_grid =: (3 1 $ ' ') , hpadded_grid , (3 1 $ ' ')
    NB. traversal vectors
    directions =: 8 2 $ 1 0 1 1 0 1 _1 1 _1 0 _1 _1 0 _1 1 _1
    NB. rpos cpos matches rdir cdir if the string starting at rpos cpos in
    NB. direction rdir cdir is the string we want
    matches =: 4 : 0
    */ ,'XMAS' -: padded_grid {~ <"1 x +"1 y *"1 0 i. 4
    )"1
    positions =: (3 + i. 0 { $ grid) ,"0/ (3 + i. 1 { $ grid)
    result1 =: +/, positions matches/ directions
    
    NB. pairs of traversal vectors
    x_directions =: 4 2 2 $ 1 1 _1 1 1 1 1 _1 _1 _1 _1 1 _1 _1 1 _1
    NB. rpos cpos x_matches 2 2 $ rdir1 cdir1 rdir2 cdir2 if there is an 'A' at
    NB. rpos cpos and the string in each of dir1 and dir2 centered at rpos cpos
    NB. is the string we want
    x_matches =: 4 : 0
    NB. (2 2 $ rdir1 cdir1 rdir2 cdir2) *"1 0/ (_1 + i.3) yields a matrix
    NB. 2 3 $ (_1 * dir1) , (0 * dir1) , (1 * dir1) followed by the same for dir2
    */ ,'MAS' -:"1 padded_grid {~ <"1 x +"1 y *"1 0/ _1 + i. 3
    )"1 2
    result2 =: +/, positions x_matches/ x_directions
    

  • J

    We can take advantage of the manageable size of the input to avoid explicit looping and mutable state; instead, construct vectors which give, for each character position in the input, the position of the most recent do() and most recent don't(); for part 2 a multiplication is enabled if the position of the most recent do() (counting start of input as 0) is greater than that of the most recent don't() (counting start of input as minus infinity).

    load 'regex'
    
    raw =: fread '3.data'
    mul_matches =: 'mul\(([[:digit:]]{1,3}),([[:digit:]]{1,3})\)' rxmatches raw
    
    NB. a b sublist y gives elements [a..b) of y
    sublist =: ({~(+i.)/)~"1 _
    
    NB. ". is number parsing
    mul_results =: */"1 ". (}."2 mul_matches) sublist raw
    result1 =: +/ mul_results
    
    do_matches =: 'do\(\)' rxmatches raw
    dont_matches =: 'don''t\(\)' rxmatches raw
    match_indices =: (<0 0) & {"2
    do_indices =: 0 , match_indices do_matches  NB. start in do mode
    dont_indices =: match_indices dont_matches
    NB. take successive diffs, then append length from last index to end of string
    run_lengths =: (}. - }:) , (((#raw) & -) @: {:)
    do_map =: (run_lengths do_indices) # do_indices
    dont_map =: (({. , run_lengths) dont_indices) # __ , dont_indices
    enabled =: do_map > dont_map
    result2 =: +/ ((match_indices mul_matches) { enabled) * mul_results
    


  • J

    There is probably a way to write this more point-free. You can definitely see here the friction involved in the way J wants to regard lists as arrays: short rows of the input matrix are zero padded, so you have to snip off the padding before you process each row, and that means you can’t lift some of the operations back up to the parent matrix because it will re-introduce the padding as it reshapes the result; this accounts for a lot of the "1 everywhere (you can interpret v"1 as “force the verb v to operate on rank 1 subarrays of the argument”).

    data_file_name =: '2.data'
    data =: > 0 ". each cutopen toJ fread data_file_name
    
    NB. {. take, i. index of; this removes trailing zeros
    remove_padding =: {.~ i.&0
    
    NB. }. behead, }: curtail; this computes successive differences
    diff =: }. - }:
    
    NB. a b in_range y == a <: y <: b
    in_range =: 4 : '(((0 { x) & <:) * (<: & (1 { x))) y'
    
    NB. a row is safe if either all successive differences are in [1..3] or all in [_3.._1]
    NB. +. or
    ranges =: 2 2 $ 1 3 _3 _1
    row_safe =: (+./"1) @: (*/"1) @: (ranges & (in_range"1 _)) @: diff @: remove_padding
    
    result1 =: +/ safe"1 data
    
    NB. x delete y is y without the xth element
    delete =: 4 : '(x {. y) , ((>: x) }. y)'"0 _
    modified_row =: 3 : 'y , (i.#y) delete y'
    
    modified_row_safe =: 3 : '+./"1 row_safe"1 modified_row"1 y'
    result2 =: +/ modified_row_safe data
    


  • The equation shown is a type of decomposition of a Lie algebra g that was introduced by Élie Cartan in his doctoral thesis. h is called a Cartan subalgebra of g.

    To answer what a Lie algebra is, an extremely hand-wavy description might be: a Lie group is a continuous group of symmetries of some geometric object (for example, the group SO(3) of rotations of three-dimensional space), and the corresponding Lie algebra is the “tangent space” to the group, that is, the space of tiny changes you can make that lie “along” the group.

    A lot of things in Lie theory and differential geometry are named after Élie Cartan, or sometimes after his son Henri.





  • Elementary school ystael spent a lot of time on Pinball Construction Set on the C64. I think I always turned the physics up to max speed minimum friction, so scoring on my tables was more about flailing and blind luck.

    My favorite C64 game, though, was one I didn’t get to play often because I had to borrow it from a friend. (Didn’t know about cracking yet.) That was Ultimate Wizard. The platform physics were kind of terrible compared to Mario, but I loved the way each level was a tiny puzzle-maze, with different treasures moving different blocks when you grabbed them, and one magic spell - just one on each level, out of ten or so - to help you deal with the enemies. And my favorite thing in every game: a level editor! No, my levels weren’t good, they were awful. But I loved laying out the little bricks and skulls and fires anyway.


  • Put a shocking amount of time into Unicorn Overlord last week.

    I think they executed the cross between Fire Emblem and Ogre Battle very well. Squad composition makes up for the lack of individual customization that is typical of the FE lineage of strategy RPGs (as opposed to the FFT/Tactics Ogre line). The overworld management is a fun exploration side activity that isn’t as time-consuming as Three Houses’s social stuff. Basiscape brought its usual excellent soundtrack, and Vanillaware their usual impressively detailed art. Plot is whatever, I don’t play these games for the plot, I play them to make anime sprites stab each other so numbers go up. So, yeah, it’s fun.

    (No, I don’t actually like Disgaea that much, mostly because “figuring out how to break the game is the game” doesn’t appeal to me.)




  • ystael@beehaw.orgtoGaming@beehaw.orgBest PS2 games?
    link
    fedilink
    arrow-up
    2
    ·
    edit-2
    9 months ago

    Was hoping someone would mention Shadow Hearts and Wild Arms! The PS2 truly was the janky AA JRPG console of all time. Also don’t forget

    • Shin Megami Tensei: Nocturne
    • Digital Devil Saga 1-2
    • Breath of Fire: Dragon Quarter
    • Stella Deus
    • Magna Carta: Tears of Blood On second thought do forget this one

  • There are a few different issues interacting here.

    1. The “family mode” users that require PIN are a child protection measure, and are not connected to Family Sharing. Remove the PIN from all adult accounts. Now you will see your whole library and be able to go to the store, and when you switch to your son’s user, he will not be able to go to the store and will only see the games you have done “Add to Family Games” on. This is how my library is set up: sharing to my partner and child, only child’s account has PIN.

    2. I don’t know the cause of your experience with the keyboard, but if you remove the PIN from your own account, that should make it less painful.

    3. This is just the way the Steam client works, not a Deck-specific feature: you are logged into one account until you change it. The PS5 is the same way.

    4. In my experience, failure to separate game state between users is a game-by-game problem. Most Windows-native games running in Proton separate their saves by user correctly. (I do not know whether this happens because the Deck generates a completely clean Proton environment for each Steam user, or whether the Proton environment is shared and the game is just doing what it would do on a Windows PC to separate saves.) The games where I have seen saves wrongly shared, ironically, are all games with native Linux ports.

    5. If you haven’t already, switch to your son’s account, unlock the PIN, and go through all the Steam multiplayer/chat settings. We have all that turned off for our child. As far as I know, a game family-shared to a user should behave exactly as if the user owned the game, from a functional point of view.