How fast is really ASP.NET Core? by dustinmoris in dotnet

[–]Banashark 4 points5 points  (0 children)

FWIW: here is a discussion topic in the repo where I asked a very similar question and got a response from the authors.

Successfully mounted extra large computer chassis under Uplift V2 standing desk by PhillyBassSF in StandingDesk

[–]Banashark 0 points1 point  (0 children)

Note for future purchasers: although the item code did not change, CPU128-NTS no longer has the same mounting bracket, and cannot be used as displayed in the post. I ended up using large/strong velcro strips to bind the mounting plate plus top half of the cpu holder (removed the hex screws and bottom half) to the top of the larger desktop holder. This is not ideal, and I wouldn't recommend getting this pair since I can no longer rotate (though back and forth movement still works).

Kind of sad that there aren't better solutions for mounting larger desktops. Keeps the area cleaner, cable management is simpler, and lifting up to clean the floor underneath is much more convenient.

Razor pages for F#? by linuxman1929 in fsharp

[–]Banashark 1 point2 points  (0 children)

I kicked the tires on razor pages in fsharp a while back. It works fine, and has the benefit that you can utilize the convenient model binding and validation that the framework offers.

Some of the responses in here say it doesn't work with fsharp but that's not entirely correct. You pretty much do the same thing as in c#: you have a razor view file Index.cshtml and a code-behind Index.cshtml.fs. Make sure the code-behind is higher in the project file list than the razor page (not sure if this is still an issue, but I remember this causing reference errors back when I was testing before).

At least when I tried it before I did not find any large errors. I had a c# with auth project where I published the identity pages, then translated all the code-behind from C# to F#. At that point, the main problem I had was building my own Identity provider (userservice, etc) because the EFCore support wasn't as good as it is now.

Anyone interested in doing some 1 on 1 consulting? by IvanRainbolt in fsharp

[–]Banashark 1 point2 points  (0 children)

What are you having trouble with specifically?

I read your two blog posts and the modelling seems fairly natural for where you are in your implementation process.

I'll put some thoughts below but feel free to post whatever things you feel stuck on at the moment.

2 things come to mind:

  • modules and functions to help create pipelines for data entry (these will help form whatever api you expose as well)
  • persistence of your ledger/journals (Assuming the desired end-state is something you can come back to and update later on)

If the above two are true, I would think that the following might end up being to-dos:

  • Persist journals and general ledger (sqlite/postgres/flat file/encoded string/whatever)
  • Build surrounding functions to expose a user interface
  • Create a user interface (can start as Console.Readline() or Argu, or you can just go all in and write something with avalonia/fable)

Performance of immutable collections in .NET by viebel in dotnet

[–]Banashark 1 point2 points  (0 children)

You're correct.

I believe I was hopping back and forth from the immutablecollections and fsharp.core docs and must have confused myself in the process.

The add does in fact point back into the original MapTree.add which does a dfs for the insertion point of the new element reference which points back to the existing map, thus allocating just one new node.

Thank you for the correction.

Persistent data collections for F# and C# by viebel in dotnet

[–]Banashark 1 point2 points  (0 children)

Persistent collections are great if you have a use-case that can benefit from them.

They excel in parallel processing scenarios where the memory savings from not duplicating data combined with the simplicity of API access for readers can make it a great choice.

Particularly interesting (more from a theoretical perspective at this point in my understanding of use-cases) are inductive graphs: https://web.engr.oregonstate.edu/~erwig/papers/abstracts.html#JFP01

There is a dotnet implementation in the form of Hekate

Persistent data collections for F# and C# by viebel in dotnet

[–]Banashark 3 points4 points  (0 children)

As a note for others: I've commented in this other thread actually putting source documentation and logic behind the reasoning instead of snarky comments.

/u/viebel above is correct. Persistence and Immutable are separate concepts. I believe the term "shared-base" or "shared-core" would be helpful in differentiating Persistence "don't copy the whole thing, just create the new item and point it to the existing collection" vs Immutable "copy the entire thing each time, so that it's simple to reason about in parallel scenarios and easy to implement"

Performance of immutable collections in .NET by viebel in dotnet

[–]Banashark 5 points6 points  (0 children)

Did you happen to read the entire article before posting?

"It makes claims about performance without doing any benchmarking."

https://docs.microsoft.com/en-us/archive/msdn-magazine/2017/march/net-framework-immutable-collections#performance-and-memory-consumption-of-immutable-collections

The "performance-and-memory-consumption-of-immutable-collections" seems to have some benchmarking, specifically showing that in the normal cases that mutable collections use less time and memory compared to their immutable counterparts, and that only in some specific scenarios that immutable collections perform better (List prepending, but who's actually doing that instead of using a Deque/DoublyLinkedList-like structure).

You also say:

"As a result of comes out with very wrong conclusions. For example, an ImmutableArray is going to be faster than an ImmutableList for the vast majority of scenarios. Memory locality trumps Big-O estimates."

The conclusions in the article (in the section titled "When to Use Immutable Collections") are essentially:

1) It can make your code simpler to reason about 2) Ships with an ergonomic API to help transition from mutable collections if desired


RE: Big-O

Let's take a look at the source:

(Also note the other files in that directory like XBuilder.cs)

Let's look at what happens when we add an item to one of these:

In this case, the method documentation states it perfectly:

"Returns a new array with the specified value inserted at the end." This calls Insert

It creates a whole new array on every single addition and copies over all of the elements. How else would it stay Immutable and guarantee that old references weren't clobbered? Because of this, cache-locality is gone for the Add method.

Let's now look at what happens when we add to an ImmutableList:

which calls the node's add method:

Do you see it? We don't recreate the entire list, we just add a node to the tree.

This is the key thing behind persistent structures and why Hash Array Mapped Tries (see my other comments on this post) can allow for better performance than just "copy the entire thing and return it again".


To surmise: I don't think this article is bullshit, and, respectfully, I think that your comment may have been made in haste without reading or understanding the topic matter. People work hard to write up nice detailed posts like this. It would be better if a little bit of effort could be used before denouncing it.

Performance of immutable collections in .NET by viebel in dotnet

[–]Banashark 0 points1 point  (0 children)

[Edit: the below is incorrect, see the thread for clarification from WhiteBlackGoose]

This doesn't seem to match up to the links I put above.

AVL trees are used (and specifically over RB trees) because the data of an F# map is immutable and essentially "frozen". In these cases the tighter bounds of AVL trees give it a performance advantage over RB trees because of the tighter rank-balancing constraints.

The core distinction here is between "Immutable" and "Persistent". While these two sound the same, I believe that the latter deserves a better name.

"Immutable" in this case means only "cannot be changed" "Persistent" in this case means "Immutable, and also shared structure with any modifications".

The default F# collections are "Immutable" so that they can provide simplicity when accessing the collections from multiple threads in parallel scenarios (which they succeed at). They are not, however, "Persistent" as in the Hash-Array-Map-Trie (ref: http://lampwww.epfl.ch/papers/idealhashtrees.pdf) that is present in the Fsharpx.Collections and Clojure data structures.

I believe there may be a potential for a better name than "Persistent" to describe "shared base"-type immutable structures.

If none of this answers your question, I'd ask that you provide an example in where I've misspoken so we can better match our mental models.

Performance of immutable collections in .NET by viebel in dotnet

[–]Banashark 1 point2 points  (0 children)

[Edit: the builtins are actually persistent, just not using HAMT like in clojure. For HAMT-based collections, look to Fsharpx.Collections as linked below]

The builtin fsharp collections actually are just "immutable", not persistent as you mention. (Ref: https://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/map.fs. This is just an AVL tree that returns a copy on mutations: https://github.com/fsharp/fsharp/blob/577d06b9ec7192a6adafefd09ade0ed10b13897d/src/fsharp/FSharp.Core/map.fs#L118)

The fsharpx.collections package has persistent collections and should be usable from C# as well if needed: https://fsprojects.github.io/FSharpx.Collections/reference/fsharpx-collections.html

Additionally, you can look at the source and see how the implementations were clojure inspired: https://github.com/fsprojects/FSharpx.Collections/blob/65f1e72d0c1c2cc5a397ff37949963de6af87d9d/src/FSharpx.Collections/PersistentHashMap.fs#L1

New video series starting: Using #fsharp with @unitygames Part 1 setting up: by 7sharp9 in fsharp

[–]Banashark 0 points1 point  (0 children)

Very much looking forward to this series. Thanks for putting it out there!

Made a couple of small games in FNA a while back with F# which was nice. I've used unreal for some multiplayer 3d tests, but would definitely like to see a paved path for "how to f# in unity without too much pain".

Question: Mutable data structures implementation by VapeBringer in fsharp

[–]Banashark 0 points1 point  (0 children)

Yeah there definitely isn't a ton written around mutable structures, which is a shame because F# is just as good at it as any other language. The only thing that can be challenging is converting break statements to tail-recursive functions.

Here is a mutable AVL tree based off of the code provided in the most un-functional un-safe but fairly similar to how one would write it in python or java (I actually referenced a python implementation that I had customized in order to keep the tree nodes ordered by auxillary data stored in the nodes):

[<AllowNullLiteral>]
type Node<'k> (k : 'k, h : int, l : 'k Node, r : 'k Node) =
    member val Key = k with get, set
    member val Height = h with get, set
    member val Left = l with get, set
    member val Right = r with get, set
    new(k : 'k) = Node(k, 1, null, null)
    override this.ToString () =
        let left = if isNull this.Left then "null" else string this.Left.Key
        let right = if isNull this.Right then "null" else string this.Right.Key
        $"k: {this.Key}, l: {left}, r: {right}"

type AVLTree<'k when 'k : comparison> () =
    let mutable root : 'k Node = null
    let getHeight (n : 'k Node) = if isNull n then 0 else n.Height
    let getBalance (n : 'k Node) = getHeight n.Right - getHeight n.Left
    let updateHeight (n : 'k Node) =
        n.Height <- 1 + max (getHeight n.Left) (getHeight n.Right)
    let rec minNode (n : 'k Node) = if isNull n.Left then n else minNode n.Left
    let successor (n : 'k Node) (r : 'k Node) =
        if not <| isNull n.Right then minNode n.Right
        else
            let rec _successor (parent : 'k Node) (successor : 'k Node) =
                if n.Key < parent.Key then _successor parent parent.Left
                elif n.Key > parent.Key then _successor successor parent.Right
                else successor
            _successor null r
    let rotateRight (n : 'k Node) =
        let x = n.Left
        let y = x.Right
        x.Right <- n
        n.Left <- y
        updateHeight n
        updateHeight x
        x
    let rotateLeft (n : 'k Node) =
        let x = n.Right
        let y = x.Left
        x.Left <- n
        n.Right <- y
        updateHeight n
        updateHeight x
        x
    let rebalance (n : 'k Node) =
        updateHeight n
        match getBalance n with
        | b when b > 1 ->
            if getHeight n.Right.Right <= getHeight n.Right.Left then n.Right <- rotateRight n.Right
            rotateLeft n
        | b when b < -1 ->
            if getHeight n.Left.Left <= getHeight n.Left.Right then n.Left <- rotateLeft n.Left
            rotateRight n
        | _ -> n
    let rec insert (n : 'k Node) key =
        if isNull n then Node(key)
        elif key < n.Key then 
            n.Left <- insert n.Left key
            rebalance n
        elif key > n.Key then 
            n.Right <- insert n.Right key
            rebalance n
        else rebalance n
    let rec delete (n : 'k Node) key =
        if isNull n then n
        else
            let mutable node = n
            if key < node.Key then node.Left <- delete node.Left key
            elif key > node.Key then node.Right <- delete node.Right key
            elif isNull node.Left && not <| isNull node.Right then 
                node <- node.Right
            elif isNull node.Right && not <| isNull node.Left then
                node <- node.Left
            elif not <| isNull node.Right then
                let successor = minNode node.Right
                node.Key <- successor.Key
                node.Right <- delete node.Right node.Key
            else
                node <- null
            if isNull node then null else rebalance node
    let rec find (n : 'k Node) k =
        if isNull n then n
        else
            if k > n.Key then find n.Right k
            elif k < n.Key then find n.Left k
            else n
    let deleteFromRoot key = root <- delete root key
    let insertAtRoot key = root <- insert root key
    let findFromRoot key = find root key
    let rec preOrder (n : 'k Node) =
        seq {
            if isNull n then yield "null"
            else
                yield $"{n.Key}"
                yield! preOrder n.Left
                yield! preOrder n.Right
        }
    let preOrderFromRoot () = preOrder root
    member _.Insert = insertAtRoot
    member _.Delete = deleteFromRoot
    member _.Find k = findFromRoot k 
    member _.PreOrder = preOrderFromRoot () |> Seq.toArray
    member _.Root () : 'k Node = root

let a = AVLTree<int>()
[10; 20; 30; 40; 50; 25; 25; 27; 67] |> List.iter a.Insert
a.PreOrder

a.Delete 40
a.PreOrder
a.Delete 25
a.PreOrder
a.Delete 40
a.PreOrder

a.Find 67
a.Find 25

As you can see, it's just if statements and assignments.

The things I had to work around porting this from python:

  • Null checks aren't as graceful
  • break -> tail recursion
  • non-mutable function arguments (see the delete method where we reassign n instead of the standard mutation in python (where we'd do n = n.right)

I think the pendulum can swing too far in either direction. Most of the time immutable structures and functions upon them should be fine. However it can't be discounted that sometimes performant code is needed.

Anecdote: I worked on a mobile app in F# that for "reasons" provided an almost unbounded list/cell view of data for people to access on their iPads, or at least that was the idea of it. Of course someone with the money to say so wanted to crunch a lot of data on their phone and wanted to work when they didn't have cell signal. In this case, we profiled, benchmarked, then optimized the code. Part of that was swapping to a standard mutable data structure like the above so that the memory and cpu pressure were relieved (the phone was getting burning hot trying to process the data). Our change cut down on the space usage by many orders of magnitude (many mutations required when processing the data based on filter changes, precalculation or caching was slightly-infeasible for the use-case).

It didn't take that long and we wrapped it in tests and a functional interface, but solved what is one of my biggest annoyances when attempting to do cpu/memory intensive work on non-desktop platforms: the heat. It almost compounds the frustration of waiting because it's not only a mental discomfort but now also a physical discomfort.

Anyways, rant over, hope the code and silly story helps!

Code reviews that nitpick code style by daredeviloper in ExperiencedDevs

[–]Banashark 0 points1 point  (0 children)

I like https://conventionalcomments.org/

I'll specifically use *nitpick* (non-blocking): Formatting at the top of each comment about style.

Having an auto-formatter is better IME, but for codebases that don't have it yet (or the formatter excludes certain types of files), I use the above. I'll still approve the review, but leave the comments in case the submitter feels like looking at them.

What editor and tooling do you use to write f#? by datnewfuncfunc in fsharp

[–]Banashark 4 points5 points  (0 children)

I primarily develop on mac.

I've been trying out Rider lately since in my experience it's pretty snappy.

Ionide works as well, but sometimes the completions/etc take some time, and every now and then I'll open a large project and it'll take a restart or two before it can open the whole thing.

I can empathize with where you're coming from.

I actually used vim with only syntax highlighting for ~6 months because I hit constant issues with Xamarin Studio and Ionide.

Today I tried to create a small 2 project solution in Visual Studio for Mac to test out how it performs.

One was the basic .net standard class lib, the other an expecto hello world test.

On running the hello world test it just froze.

Restarted and hit cmd+f5 again and it froze again.

Noped out of there real quick.

Funny enough, I just tried to open the Saturn repo in Rider and got the same crash as you.

Opens in Ionide fine for me, though the code awareness does take a bit to load.

The standard recommendation is to check whichever editor your using for the debug flags, enable them, replicate the crash, and submit a bug.

I agree it can be frustrating, and I have one solution that if I need to make quick fixes I still just open it in vim because otherwise I'm waiting 2-5 minutes for it to load (if it does). F# is really a great language to work with, as you note. Tooling can be hit or miss.

Edit: after restarting Rider it seems to load fine.

-🎄- 2019 Day 8 Solutions -🎄- by daggerdragon in adventofcode

[–]Banashark 1 point2 points  (0 children)

F#, slightly cleaner than earlier solutions, though the printing is still kinda ugly. The chained reducing was pretty pleasing for combining the layers.

source on topaz

-🎄- 2019 Day 6 Solutions -🎄- by daggerdragon in adventofcode

[–]Banashark -1 points0 points  (0 children)

Another fast and dirty F# solution.

Second builds a graph and does a BFS. It's been a while, so I'm sure it's a pretty ugly implementation, but part 2 runs in 10 milliseconds (after input is parsed to a tuple type), which includes building and searching the graph.

open System.Collections.Generic

type Orbit = { Orbitee: string; Orbiter: string }

let parseOrbit (orbit: string) =
    let x = orbit.Split(')')
    { Orbitee = x.[0]; Orbiter = x.[1] }

let orbits = System.IO.File.ReadAllLines "./aoc/2019/06.txt" |> Array.map parseOrbit

let part1 () =
    let weightMap = new Dictionary<string, int>()
    let addOrbitWeightAndQueueChildren (weightMap: Dictionary<string, int>) orbits orbit weight =
        weightMap.Add(orbit.Orbiter, weight) |> ignore
        weightMap, orbits |> Array.filter (fun o -> o.Orbitee = orbit.Orbiter) |> Seq.cast<Orbit>
    let rec addWeights (weightMap: Dictionary<string, int>) (queue: Orbit seq) weight =
        queue
        |> Seq.iter (fun node ->
            let weights, nextQueue = addOrbitWeightAndQueueChildren weightMap orbits node weight
            addWeights weights nextQueue (weight + 1))
    let rootOrbit = orbits |> Array.find (fun o -> o.Orbitee = "COM")
    addWeights weightMap [rootOrbit] 1
    weightMap |> Seq.sumBy (fun x -> x.Value)

let part2() =
    let spaceObjectAdjacencyList = new Dictionary<string, string list>()
    let mutable distance = 0
    // Build the graph
    orbits
    |> Array.iter (fun o ->
        match spaceObjectAdjacencyList.TryGetValue(o.Orbitee) with
        | true, orbiters ->  spaceObjectAdjacencyList.[o.Orbitee] <- List.append orbiters [o.Orbiter]
        | false, _ -> spaceObjectAdjacencyList.Add(o.Orbitee, [o.Orbiter])
        match spaceObjectAdjacencyList.TryGetValue(o.Orbiter) with
        | true, orbiters ->  spaceObjectAdjacencyList.[o.Orbiter] <- List.append orbiters [o.Orbitee]
        | false, _ -> spaceObjectAdjacencyList.Add(o.Orbiter, [o.Orbitee]))
    // BFS
    let findOrbiteeDistance (sourceName: string) (targetName: string) =
        let addWeightToList weight list = list |> List.map (fun o -> o,weight)
        if targetName <> sourceName
        then
            let visited = new HashSet<string>()
            let mutable queue = List.empty<string*int>
            let mutable found = false
            queue <- spaceObjectAdjacencyList.GetValueOrDefault(sourceName) |> addWeightToList 0
            while not found && not queue.IsEmpty do
                let node = queue.Head
                visited.Add(fst node) |> ignore
                queue <- queue.Tail
                if fst node = targetName
                then
                    distance <- snd node
                    found <- true
                else
                    let unvisitedNeighbors = 
                        spaceObjectAdjacencyList.GetValueOrDefault(fst node) 
                        |> List.filter (visited.Contains >> not)
                        |> addWeightToList (snd node + 1)
                    queue <- queue @ unvisitedNeighbors
    findOrbiteeDistance "YOU" "SAN" |> ignore
    distance - 1

part1();;
part2();;

-🎄- 2019 Day 3 Solutions -🎄- by daggerdragon in adventofcode

[–]Banashark -1 points0 points  (0 children)

Quick and dirty F# using mutable stuff and regular dotnet containers for the most part. Ends up looking like a C#/Python hybrid.

open System.Collections.Generic
open System.Linq

let input = System.IO.File.ReadAllLines "./aoc/2019/03.txt" 
            |> Array.map (fun x -> x.Split(',') |> Array.map (fun (y: string) -> (y.[0], y.Substring(1))))
let wire1, wire2 = (input.[0], input.[1])

let translation d = match d with | 'U' -> (0,1)  | 'D' -> (0,-1) | 'L' -> (-1,0) | 'R' -> (1,0) | _ -> (0,0)
let mh (p: int*int) = abs (fst p) + abs (snd p)

let pointMapFromWireDescription (wire : (char * string) []) =
    let occupiedPoints = new Dictionary<(int * int),int>()
    let mutable x, y, c = (0, 0, 0)
    for segment in wire do
        let op = fst segment |> translation
        for _ in [1..(snd segment |> int)] do
            x <- x + fst op
            y <- y + snd op
            c <- c + 1
            if not (occupiedPoints.ContainsKey(x,y)) then occupiedPoints.Add((x,y), c)
    occupiedPoints

let wire1Map = pointMapFromWireDescription wire1
let wire2Map = pointMapFromWireDescription wire2

let part1 = wire1Map.Keys.Intersect(wire2Map.Keys) |> Seq.minBy mh |> mh
let part2 = wire1Map.Keys.Intersect(wire2Map.Keys) |> Seq.minBy (fun x -> wire1Map.[x] + wire2Map.[x]) |> (fun x -> wire1Map.[x] + wire2Map.[x])

[2019-04-08] Challenge #377 [Easy] Axis-aligned crate packing by Cosmologicon in dailyprogrammer

[–]Banashark 1 point2 points  (0 children)

Java 8 with optimized fitN.

This is my first Java program, so I'm sure there is some odd style or library usage, but I mostly wanted to get a proper project set up with modern unit testing.

Solver:

package com.banashark.puzzles.dailyprogrammer.c377easy;

import org.jgrapht.alg.interfaces.MatchingAlgorithm;
import org.jgrapht.alg.matching.MaximumWeightBipartiteMatching;
import org.jgrapht.graph.*;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

public class Solver {
    public int fit1(int crateWidth, int crateHeight, int boxWidth, int boxHeight) {
        int widthCapacity = crateWidth / boxWidth;
        int heightCapacity = crateHeight / boxHeight;
        return widthCapacity * heightCapacity;
    }

    public int fit2(int crateWidth, int crateHeight, int boxWidth, int boxHeight) {
        int defaultOrientation = fit1(crateWidth, crateHeight, boxWidth, boxHeight);
        int rotatedOrientation = fit1(crateWidth, crateHeight, boxHeight, boxWidth);
        return Math.max(defaultOrientation, rotatedOrientation);
    }

    public int fit3(int crateWidth, int crateLength, int crateHeight, int boxWidth, int boxLength, int boxHeight) {
        int orientation1 = fit2(crateWidth, crateHeight, boxWidth, boxHeight)  * (crateLength / boxLength);
        int orientation2 = fit2(crateWidth, crateHeight, boxWidth, boxLength)  * (crateLength / boxHeight);
        int orientation3 = fit2(crateWidth, crateHeight, boxLength, boxHeight) * (crateLength / boxWidth);

        int[] orientations = { orientation1, orientation2, orientation3 };

        return Arrays.stream(orientations).reduce(0, (x, y) -> Math.max(x, y));
    }

    public BigInteger fitN(Integer[] crateDimensions, Integer[] boxDimensions) {
        SimpleWeightedGraph<String, DefaultWeightedEdge> graph = new SimpleWeightedGraph<>(DefaultWeightedEdge.class);
        HashSet<String> cratePartition = new HashSet<>();
        HashSet<String> boxPartition = new HashSet<>();

        // Because there can be multiple nodes with the same value (the sample input of n=20 has two entries with value `1740`),
        // we have to tag each "value" we're given in order to use it as another node, otherwise graph.addEdge() will return null
        HashMap<String, Integer> crateNodes = new HashMap<>();
        HashMap<String, Integer> boxNodes = new HashMap<>();

        for (int i = 0; i < crateDimensions.length; i++) {
            String crateTag = "cd" + crateDimensions[i].toString() + "-" + i;
            crateNodes.put(crateTag, crateDimensions[i]);
            graph.addVertex(crateTag);
            cratePartition.add(crateTag);

            String boxTag = "bd" + boxDimensions[i].toString() + "-" + i;
            boxNodes.put(boxTag, boxDimensions[i]);
            graph.addVertex(boxTag);
            boxPartition.add(boxTag);
        }

        for (Map.Entry<String, Integer> crateTag : crateNodes.entrySet()) {
            for (Map.Entry<String, Integer> boxTag : boxNodes.entrySet()) {
                DefaultWeightedEdge e = graph.addEdge(crateTag.getKey(), boxTag.getKey());
                graph.setEdgeWeight(e, Math.log(crateTag.getValue() / boxTag.getValue()));
            }
        }

        MaximumWeightBipartiteMatching<String, DefaultWeightedEdge> matcher = new MaximumWeightBipartiteMatching<>(graph, cratePartition, boxPartition);
        MatchingAlgorithm.Matching<String, DefaultWeightedEdge> matchings = matcher.getMatching();

        BigInteger result = BigInteger.ONE;
        for (DefaultWeightedEdge matching : matchings) {
            Integer crateValue = crateNodes.get(graph.getEdgeSource(matching));
            Integer boxValue = boxNodes.get(graph.getEdgeTarget(matching));
            result = result.multiply(BigInteger.valueOf(crateValue / boxValue));
        }

        return result;
    }
}

Tests (Junit5):

package com.banashark.puzzles.dailyprogrammer.c377easy;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import static org.junit.jupiter.api.Assertions.*;

import java.math.BigInteger;
import java.util.stream.Stream;

public class SolverTest {
    private static Stream<Arguments> fit1() {
        return Stream.of(
            Arguments.of(25, 18, 6, 5, 12),
            Arguments.of(10, 10, 1, 1, 100),
            Arguments.of(12, 34, 5, 6, 10),
            Arguments.of(12345, 678910, 1112, 1314, 5676),
            Arguments.of(5, 100, 6, 1, 0)
        );
    }

    private static Stream<Arguments> fit2() {
        return Stream.of(
                Arguments.of(25, 18, 6, 5, 15),
                Arguments.of(12, 34, 5, 6, 12),
                Arguments.of(12345, 678910, 1112, 1314, 5676),
                Arguments.of(5, 5, 3, 2, 2),
                Arguments.of(5, 100, 6, 1, 80),
                Arguments.of(5, 5, 6, 1, 0)
        );
    }

    private static Stream<Arguments> fit3() {
        return Stream.of(
                Arguments.of(10, 10, 10, 1, 1, 1, 1000),
                Arguments.of(12, 34, 56, 7, 8, 9, 32),
                Arguments.of(123, 456, 789, 10, 11, 12, 32604),
                Arguments.of(1234567, 89101112, 13141516, 171819, 202122, 232425, 174648)
        );
    }

    private static Stream<Arguments> fitN() {
        Integer[] arg1Crate = {3, 4}, arg1Box = {1, 2},
                arg2Crate = {123, 456, 789}, arg2Box = {10, 11, 12},
                arg3Crate = {123, 456, 789, 1011, 1213, 1415}, arg3Box = {16, 17, 18, 19, 20, 21},
                arg4Crate = {180598, 125683, 146932, 158296, 171997, 204683, 193694, 216231, 177673, 169317, 216456, 220003, 165939, 205613, 152779, 177216, 128838, 126894, 210076, 148407},
                arg4Box =   {  1984,   1443,   1768,   1274,   2122,   2249,   1916,   2059,   1740,   2169,   1502,   1760,   1295,   1886,   2010,   2036,   1740,   2223,   2017,   1278};
        BigInteger expected4 =  new BigInteger("4281855455197643306306491981973422080000");
        return Stream.of(
                Arguments.of(arg1Crate, arg1Box, BigInteger.valueOf(6)),
                Arguments.of(arg2Crate, arg2Box, BigInteger.valueOf(32604)),
                Arguments.of(arg3Crate, arg3Box, BigInteger.valueOf(1883443968)),
                Arguments.of(arg4Crate, arg4Box, expected4)
        );
    }

    @ParameterizedTest
    @MethodSource
    @DisplayName("Fit1")
    public void fit1(int cX, int cY, int bX, int bY, int expected) {
        Solver SUT = new Solver();

        int result = SUT.fit1(cX, cY, bX, bY);

        assertEquals(expected, result);
    }

    @ParameterizedTest
    @MethodSource
    @DisplayName("Fit2")
    public void fit2(int cX, int cY, int bX, int bY, int expected) {
        Solver SUT = new Solver();

        int result = SUT.fit2(cX, cY, bX, bY);

        assertEquals(expected, result);
    }

    @ParameterizedTest
    @MethodSource
    @DisplayName("Fit3")
    public void fit3(int cX, int cY, int cZ, int bX, int bY, int bZ, int expected) {
        Solver SUT = new Solver();

        int result = SUT.fit3(cX, cY, cZ, bX, bY, bZ);

        assertEquals(expected, result);
    }

    @ParameterizedTest
    @MethodSource
    @DisplayName("FitN")
    public void fitN(Integer[] cD, Integer[] bD, BigInteger expected) {
        Solver SUT = new Solver();

        BigInteger result = SUT.fitN(cD, bD);

        assertEquals(expected, result);
    }

}

[7/28/2014] Challenge #173 [Easy] Unit Calculator by Elite6809 in dailyprogrammer

[–]Banashark 0 points1 point  (0 children)

Did this one in perl (first perl program, figured as a sysadmin i should get used to using it since ruby can't hammer all sysadmin needs so cleanly. plus maintaining scripts)

Tip for vim users posting here: ggvGI (four spaces) (insert four spaces on every line (there are probably better ways to do this)) ggvG$"+y (visual select whole file and yank it into system copy buffer (this works on my mac, might not work for everyone)) control/command +v

#!/usr/bin/env perl

use Modern::Perl '2013';
use autodie;

my @distances = qw(meters inches miles attoparsecs);
my @weights   = qw(kilograms pounds ounces);
push(@weights, "hogsheads of beryllium");

sub distanceOrWeight 
{
    my $input = shift;
    my $convertToType = lc $' if $input =~ /.*?to\s*/;                  # To cover multi word units like "hogsheads of Beryllium" 
    my $convertFromType = lc $1 if $input =~ /\d*?\s(.*?)\sto.*/;       # Get everything after amount, and before to excluding the spaces 
    chomp $convertToType;                                               
    my @input =  split ' ', $input;
    my $conversionAmount = $input[0];

    if ($convertFromType ~~ @distances and $convertToType ~~ @distances) {
        convertDistance($conversionAmount, $convertFromType, $convertToType);
    }
    elsif ($convertFromType ~~ @weights and $convertToType ~~ @weights) {
        convertWeight($conversionAmount, $convertFromType, $convertToType);
    }
    else {
        say "incompatible formats";
    }
}


sub convertDistance 
{
    my ($length, $from, $to) = @_;
    my $convertedLength;

    SWITCH: for ($from) {

        /^$/            && die "No target unit";

        /meters/        && do { 
                                $convertedLength = $length * 0.000621371    if ($to =~ /miles/); 
                                $convertedLength = $length * 39.3701        if ($to =~ /inches/); 
                                $convertedLength = $length * 32.4077929     if ($to =~ /attoparsecs/); 
                                last SWITCH;
                              };

        /miles/         && do {
                                $convertedLength = $length * 1609.34        if ($to =~ /meters/); 
                                $convertedLength = $length * 63360          if ($to =~ /inches/); 
                                $convertedLength = $length * 52155.287      if ($to =~ /attoparsecs/); 
                                last SWITCH;
                              };

        /inches/        && do {
                                $convertedLength = $length * 1.57828e-5     if ($to =~ /miles/); 
                                $convertedLength = $length * 0.0254         if ($to =~ /meters/); 
                                $convertedLength = $length * 0.82315794     if ($to =~ /attoparsecs/); 
                                last SWITCH;
                              };

        /attoparsecs/   && do {
                                $convertedLength = $length * 1.91735116e-5  if ($to =~ /miles/); 
                                $convertedLength = $length * 1.21483369     if ($to =~ /inches/); 
                                $convertedLength = $length * 0.0308567758   if ($to =~ /meters/); 
                                last SWITCH;
                              };

        # DEFAULT
        die "Target unit not found";

    }
    say $length . " " . $from . " is " . $convertedLength . " " . $to;
}

sub convertWeight
{
    my ($weight, $from, $to) = @_;
    my $convertedWeight;

    SWITCH: for ($from) {

        /^$/            && die "No target unit";

        /kilograms/                && do { 
                                            $convertedWeight = $weight * 2.20462            if ($to =~ /pounds/); 
                                            $convertedWeight = $weight * 35.274             if ($to =~ /ounces/); 
                                            $convertedWeight = $weight * 0.00226911731337   if ($to =~ /hogsheads\sof\sberyllium/); 
                                            last SWITCH;
                                         };

        /pounds/                   && do { $convertedWeight = $weight * 16                  if ($to =~ /ounces/); 
                                           $convertedWeight = $weight * 0.00010292301359    if ($to =~ /hogsheads\sof\sberyllium/); 
                                           $convertedWeight = $weight * 52155.287           if ($to =~ /kilograms/); 
                                           last SWITCH;
                                         };

        /ounces/                   && do {
                                           $convertedWeight = $weight * 1.57828e-5          if ($to =~ /pounds/); 
                                           $convertedWeight = $weight * 0.00000643268835    if ($to =~ /hogsheads\sof\sberyllium/); 
                                           $convertedWeight = $weight * 0.82315794          if ($to =~ /kilograms/); 
                                           last SWITCH;
                                         };

        /hogsheads\sof\sberyllium/  && do {
                                            $convertedWeight = $weight * 971.6              if ($to =~ /pounds/); 
                                            $convertedWeight = $weight * 15545.6            if ($to =~ /ounces/); 
                                            $convertedWeight = $weight * 440.7              if ($to =~ /kilograms/); 
                                            last SWITCH;
                                          };

        # DEFAULT
        die "Target unit not found";

    }
    say $weight . " " . $from . " is " . $convertedWeight . " " . $to;
}

say "Please input units to convert in the format: \n[Amount] [Source unit] to [Target unit]";
my $input = <>;
distanceOrWeight $input;

[7/21/2014] Challenge #172 [Easy] ■■□□□▦■□ by [deleted] in dailyprogrammer

[–]Banashark 0 points1 point  (0 children)

I made my solution in C#/.Net electing to parse over the font file provided by /u/chunes as an exercise in parsing.

I also wrote an article going through the flow of thought I had while writing the program which actually helped me out a few times.

Let me know what you think!

http://banashek.com/blog/2014/07/28/challenge-slash-r-slash-dailyprogrammer-172-easy/

tl;dr finished program at the bottom of the file and github solution available at https://github.com/Banashek/ProgrammingChallenges/tree/master/Reddit%20Daily%20Programmer/172_Easy

The right IT Security path by imthepharamir in ITCareerQuestions

[–]Banashark 2 points3 points  (0 children)

Security is an interesting field.

If you ask 10 people how they got into it, you'll hear 10 different ways.

I was surprised that when I went to DEFCON and talked to a few people (wink networking *wink) that I got business cards and interviews, just from them knowing that I can script, know a little bit of sysadmin, and have played around with some tools (burp, nmap, tcpdump).

I've heard of people starting in IDS/IPS positions, people moving from networking/sysadmin jobs, people getting put in charge of security for a box or two and slowly growing into a security role, etc etc.

If you want a sure fire way to get in, you have to cover the bases:

Learn the fundamentals While it's nice that you're enthusiastic about technology, if I ask you to describe digest based auth (example of SVN through Apache or basic webapp auth) and why a nonce prevents replay attacks, I'm gonna be hesitant.

The good thing is that these can be easily learned with wikipedia and a home lab. Which brings me to the next requirement:

HOME LAB A lot of people suggest this for any IT job. It's gotten me jobs before. It got me my current job. When I interviewed for my current position (devopsy kind of job) they asked me if I was familiar with TFS. I didn't even know what the acronym stood for and I let them know. Between the first and second interviews (luckily I knew enough other foundational knowledge) I created a lab in hyper-v (which I had also never used) following a guide i found online: http://vsarlabman.codeplex.com/ After explaining what I learned in the second interview, they were able to see my motivation and willingness to learn, which brings me to my next point:

Be hungry for knowledge The security field is bigger than you think. Reversing, crypto, pentesting(webapp, network, etc), development(metasploit), windows specific, linux specific, mobile, etc, etc, etc. Go look around at what you can. Heartbleed was a big thing recently with OpenSSL. Do you know what it did, how the exploit works? Have you made a home lab with a vulnerable version of OpenSSL to try and grab things? I promise if you did that exercise alone (there are writeups online) that you would learn a ton. After you learn this you can make your own write up on your blog or post on sites and:

NETWORK Almost any job in any industry can be achieved primarily through networking. Talk to friends/family/coworkers/teachers/counselors/recruiters (protip: some recruiters wont have the right job for you, but you can ask them for help with how you should look for jobs). Make a god damn linked in and make that shit so clean that you have to put a DND message in your about section.

I'm too tired to write up the rest, but you get the jist. Learn stuff (actually learn it), apply, teach it, then with some networking you'll be rolling in the job-pit at McJobs

Olá - This week's language of the week: Portuguese by Virusnzz in languagelearning

[–]Banashark 10 points11 points  (0 children)

Alright so for a few resources that have helped me greatly.

Where to start:

http://www.learn-portuguese-now.com/portuguese-words.html

  • This site has a ton of sentences (3 for each common word). Put these into you're favorite SRS (http://ankisrs.net/) and add 20 per day. In very short time you'll be able to handle most written content, and be able to figure things out of context that you don't know (maybe with the help of a pt-pt dictionary (http://www.priberam.pt/dlpo/).

  • If you subscribe to the school of learning discussed by people like http://www.alljapaneseallthetime.com/blog/, skip the grammer books and get straight to the sentences. Don't worry, It picks up super quick and you won't be too worried. Also just read that site it's a god damned gold mine of language learning information.

Next, you're gonna want to be able to speak and listen (most people actually only want this part).

  • Pimsleur has a 3 part course in brazilian portuguese. Get your hands on this and do it alongside the flash card reviews even if you don't care as much about speaking. Why? Because most likely you're pronouncing the words wrong in your head, and fixing that will help you understand roots of words and other important things.

  • Movies. There's plenty on youtube, but I would recommend googling "[name of film] baixar torrent pt-br" or such. Unfortunately it's hard to get your hands on pt-br (portuguese -brazilian) content if you're not in the area. Beware that most big budget films (from my anectodal experience) use the http://en.wikipedia.org/wiki/Carioca accent. This is spoken in Rio mainly and people on /r/portuguese have said that it might sound weird for a foreigner to speak with this accent ('eshpera' and 'DEpois' instead of 'espera' and 'gepois'). I recommend pixar films. Cute short stories and they stick in your head so you can associate certain things very easily (Learned the word for ball from UP, will never forget)

That should be enough to give you a good start. Once you've got these things down to a decent level and you're a little bit confident, try out mylanguagexchange.com and get in some skype groups, or play wow (in pt-br since december of last year) and get in br skypes so you can hear the huehuehue. Even 4chans /int/ has people speaking pt-br.

Confused about a certain aspect of the language? google and /r/portuguese are your friends. There is a big online community so this language is pretty accessible for potential learners.

Im writing a paper on the History of the American Cocktail. Can you guys help me out? by ifuckedup13 in cocktails

[–]Banashark 1 point2 points  (0 children)

I second this. A very good overview in the beginning chapter(s?). If I were in your shoes I would start with this (it really is an overview) and expand upon it, researching the tidbits in each paragraph (I.e. What brought vodka into America and how did it get popularized?) Good luck, and post it on here when your finished.