What is this mess? | Collatz Conjecture

Would there be the most efficient way for me to display the tree

Here's my current view of the Collatz Conjecture

If you have better way to do it please show it to me

The source code is provided here

Comments

  • What happens (falsely, what do you mean by mess),

    What do you want to happen instead?

    Which line numbers do we have to look at please?

    Maybe the black lines annoy you, drawn in line 92?

    Thank you in advance!

    Chrisir

  • Is this a processing question?

  • Are you trying to implement an alternative to this in Processing(Java), or p5.js? This is just a javascript canvas....

  • edited February 2018

    I was watching this before and just thought that I could make and art based on the conjecture.

    So the final result was shown above in my github pages.

    My purpose is more towards a discussion rather than a question as stated on

    Would there be the most efficient way for me to display the tree

    I'm just wondering could that result produced by my current code is considered as an art or just a mere mess. That's all

    What do you guys think :D

  • Well, whether it is considered art depends on context.

    If you present it as art, I think it could certainly be received that way -- it is complex, looks designed (font, color) and has characteristics of both ornamental design (the curve patterns) and information visualization (ratios of similar elements in different sizes, configurations, and lengths that seem to reflect complex information given visual form). If you put an image of it in your art portfolio on a website or printed out a banner poster and hung it on a wall, I don't think anybody would blink.

    Of course, the 'art' would probably be even more compelling (for both audiences and for this forum) if you accompanied it with a statement about what the Collatz conjecture is, why you are visualizing it, and/or what methods you adopted and why. That would also clarify whether this was about finding a good visual form to express what you wanted, or if this was an accident you stumbled upon, and isn't part of an artistic process -- it just looks cool.

  • Yeah. I personally found it cool too.

    But, what I'm after is that "Sea weed" like pattern shown in the video. After watching that video, I thought I could recreate that design programmatically since I wouldn't think it was drawn by hand.

    Maybe it wasn't possible and was drawn by hand at all, I guess.

  • No, that seaweed pattern was definitely created programmatically, not by hand.

    The data is a directed graph; the data representation is a graph. Each node leaf is a unique number; every path is rooted in node 1.

    There are a lot of Javascript libraries for drawing a directed graph once you have the data for it -- or you could do the algorithm yourself. With data like this, if you want a fern-like result is important to start out using small rotation offsets -- like 1-5 degrees rotation -- to avoid long runs creating curling behaviors.

    There are many ways to store your graph data. A directed graph data is a PVector[] array where x is the source node id and y is the target node id. Since ids are ints, you could instead of PVector just use a list of int[2] arrays -- or you could use a hashmap with an int for a key and a list of ints for values. Since this is actually the data structure you need to use while drawing, that might be the most efficient.

  • edited March 2018

    Here is one example of generating your graph data according to the conjecture rules.

    import java.util.HashSet;
    HashMap<Integer, HashSet<Integer>> graph = new HashMap<Integer, HashSet<Integer>>();
    int counter = 10;
    
    for (int i=counter; i>1; i--) {
      // cascade from this number
      int child = i;
      // compute next number in cascade
      int parent;
      print(child);
      // Collatz Conjecture rules
      while (child!=1) {
        if (child%2==0) {
          parent = child/2;
        } else {
          parent = child*3 + 1;
        }
        // add parent to graph if it does not exist
        if (graph.get(parent) == null) {
          graph.put(parent, new HashSet<Integer>());
        }
        // add child to parent
        graph.get(parent).add(child);
        print(" ->", parent);
        child = parent;
      }
      print("\n\n");
    }
    
    println(graph);
    

    Output:

    10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1

    9 -> 28 -> 14 -> 7 -> 22 -> 11 -> 34 -> 17 -> 52 -> 26 -> 13 -> 40 -> 20 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1

    8 -> 4 -> 2 -> 1

    7 -> 22 -> 11 -> 34 -> 17 -> 52 -> 26 -> 13 -> 40 -> 20 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1

    6 -> 3 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1

    5 -> 16 -> 8 -> 4 -> 2 -> 1

    4 -> 2 -> 1

    3 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1

    2 -> 1

    And:

    {1=[2], 2=[4], 34=[11], 3=[6], 4=[8], 5=[10], 7=[14], 8=[16], 40=[13], 10=[3, 20], 11=[22], 13=[26], 14=[28], 16=[5], 17=[34], 52=[17], 20=[40], 22=[7], 26=[52], 28=[9]}

    Notice the print output from the loops follows the pen-and-paper process from the video. The graph data is assembled backwards -- leaf-to-stem -- but at the end you have a complete data structure that can easily be walked forwards -- stem-to-leaf.

    Aside: this example uses HashSet to produces unique child listings -- if you wanted to count duplicate child entries to create a heat-map effect, you could use ArrayList<Integer> instead of HashSet<Integer>, and would end up with e.g. {1=[2,2,2,2,2,2,2,2]}, 2=[4,4,4,4,4,4] et cetera.

    Now that you have all your data in your graph, you can walk the graph to draw. Start with a position for node 1, find the children (2), then assign each child a position based on whether it is odd or even.

    You can keep track of positional data for each node as you walk the graph -- for example, either by adding it to a separate global lookup table, or by turning your HashMap into a more complex graph object that also stores node positions.

    One important thing is that with random walks across even and odd numbers, you won't get a fern-like output if you represent them as absolute offsets (+x/- x). Instead, use rotation, and decrease the rotation at each step (e.g. *0.98)

Sign In or Register to comment.