Coding: Fleeting Thoughts

A place to discuss the implementation and style of computer programs.

Moderators: phlip, Moderators General, Prelates

User avatar
Peaceful Whale
Posts: 159
Joined: Sun Jul 16, 2017 10:38 pm UTC
Location: Northern Virginia

Re: Coding: Fleeting Thoughts

Postby Peaceful Whale » Mon Feb 05, 2018 11:58 am UTC

What I’m doing:
25x25x25 “playing area”
2 3D arrays. New gen and Old gen.
Changes to old gen are saved to new gen.
New gen is displayed.
New gen becomes old gen.
And then it changes are made to old gen and saved to new gen...

This will go till I tell it to stop.
I plan for it to be 2-4 generations a second, so you can see it progress.
I’m using a raspberry pi 2, so will memory and stuff really be a problem, will I need to change my code to compensate for it?
My meta for future reference
Spoiler:
cemper93 wrote:Your meta appears to be "just writes whatever is on his mind and doesn't remember what happened more than five hours ago"

User avatar
Flumble
Yes Man
Posts: 1998
Joined: Sun Aug 05, 2012 9:35 pm UTC

Re: Coding: Fleeting Thoughts

Postby Flumble » Mon Feb 05, 2018 12:28 pm UTC

If I generate a 250x250x250 list-of-lists in the python shell, it starts consuming around 500MB. (which would imply some 32 bytes per element) So don't expect a playing area that's 1000 times as small to have a problematic impact on memory.

User avatar
Soupspoon
You have done something you shouldn't. Or are about to.
Posts: 3390
Joined: Thu Jan 28, 2016 7:00 pm UTC
Location: 53-1

Re: Coding: Fleeting Thoughts

Postby Soupspoon » Mon Feb 05, 2018 1:43 pm UTC

For that size, I don't see any problem with any method, though the base overheads of the non-array/hybrid versions won't help. 25³ array is what I'd use, for that. The rest is just overkill, and awkward with it.

(Question: Have you thought about edge conditions? Are you doing wrap-around (finite but boundless, presumably toroidal) or are you adjusting the thresholds (making it, say a given percentage of the viable neighbours (26, 17, 11 or 7, assuming 1-deep influence including all diagonals), rather than absolute numbers assuming always 26 neighbours and just fudging the edge?)

It'd be interesting to see if you could use something like this 8x8x8 cube, for output. Now you've got me wondering how to mutiplex that. At some point, it'd involve three 25-pin connectors, but possibly doable with analogue voltage levels handling activation levels (e.g. 5 voltage levels, 0 to Vmax in ¼Vmax intervals, on six outputs that key a 6-digit pental discriminator, two pental digits per dimension).

(15,625 LEDs, though, and likely at least 625 transistors betwixt the first and second input 25s, whatever else you have to use to swing them high and the third 25 low on the output pin. And that's with raster-scanning illumination. Can you power an LED for 1/15625th of the time and still make it visibly lit? Perhaps you need to individually latch them on, as well, which is at least 15,625 transistors with loopbacks onto the input and the common base raised high on them all to reset/whatever.)

User avatar
Yakk
Poster with most posts but no title.
Posts: 11078
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Mon Feb 05, 2018 3:33 pm UTC

Expression templates are dumb and should feel bad.

I want operator expression( AST ) that I can overload and rewrite what happens.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

User avatar
Peaceful Whale
Posts: 159
Joined: Sun Jul 16, 2017 10:38 pm UTC
Location: Northern Virginia

Re: Coding: Fleeting Thoughts

Postby Peaceful Whale » Mon Feb 05, 2018 3:44 pm UTC

Yeah, I’ve made a set of rules for the 3D thing, we’ll se how it works.
Ones that share a vertex have a weight of 0, and ones that share an edge have a weight of .5, and ones that share a face have a weight of 1...

I might make it boundless if I want to, but then I’d use Pi3D instead of Minecraft as the graphics engine...
We’ll see how it goes, I think I’ll be able to work more on it tomorrow.
My meta for future reference
Spoiler:
cemper93 wrote:Your meta appears to be "just writes whatever is on his mind and doesn't remember what happened more than five hours ago"

User avatar
Soupspoon
You have done something you shouldn't. Or are about to.
Posts: 3390
Joined: Thu Jan 28, 2016 7:00 pm UTC
Location: 53-1

Re: Coding: Fleeting Thoughts

Postby Soupspoon » Mon Feb 05, 2018 4:48 pm UTC

Peaceful Whale wrote:I might make it boundless if I want to, but then I’d use Pi3D instead of Minecraft as the graphics engine...
Interesting. (I fell out of love with my Minecraft Pi version when I realised it was a limited size "god mode" builder, had no mobs and I couldn't even do all the things I used to do with the PC version1 that I had hogged on someone else's machine. But as a quick-and-dirty displayer of external info..? Well, that's what Pi developmemt is supposed to encourage, and only look like a game. So why not?)


But what I meant by finite-but-boundless is just how it treats the edges. For X/Y/Z of 0..24, the 'upper' neighbour of 24 is 0, and the 'lower' neighbour of 0 vice-versa. That'd be in your raw code, doesn't matter how it then gets rendered.

Pseudocode (maybe some Perlish elements, though I was aiming for generic C-family so ignore them), made flexible:

Code: Select all

define SIZE=25;

sub TrueVal(n) {
  if n<0 return n+SIZE;
  if n>=SIZE return n-SIZE;
  return n;
  // Doesn't handle going over the 0 or SIZE-1 limits by more than SIZE elements.
  // Recurse or loop until you are returning 'n' unchanged, perhaps?
  // You can also do things with modulous, as long as you correct/avoid bad behaviour in the negatives.
}
sub NeighboursOf(x,y,z) {
  Tally=0; // for later
  for (dX=-1; dX<=1; dX++) {
    for (dY=-1; dY<=1; dY++) {
      for (dZ=-1; dZ<=1; dZ++) {
        AssessedCell=Assess(TrueVal(x+dX),TrueVal(y+dY),TrueVal(z+dZ));
        // Then, however you'd prefer, add the signums (negative numbers made positive, zero is zero) of (dX, dY, dZ) together.
        // Total=3: corner neighbour (share vertex, ignore in your case)
        // Total=2: edge neighbour (share edge, add 0.5*AssessedCell to your tally)
        // Total=1: face neighbour (share face, add 1*AssessedCell to your tally)
        // Total=0: original cell (ignore? Or use to decide if it's a born/live/die/stay-dead situation.)
        // Total=anything else, fatal error. Ought to be impossible, but catch it anyway!
        TallyResult=Foo(Bar(Baz(Tally, Status(x,y,z)))); // Whatever.
        return TallyResult;
      }
    }
  }
}


(TIMTOWTDI!)


1 Beta? Pre-MS. It had the Endermen, but it was before The End and all that other magic stuff. Apparently you can work with raw magma these days having quaffed a potion to be immune. No challenge at all. One of the reasons I'm not tempted to

Tub
Posts: 381
Joined: Wed Jul 27, 2011 3:13 pm UTC

Re: Coding: Fleeting Thoughts

Postby Tub » Mon Feb 05, 2018 4:56 pm UTC

Soupspoon wrote:It's one solution, though. I wouldn't define a full Minecraft-like environment as a Dictionary-indexed 'array' with so many cells filled (even if air=null).

Unsurprisingly, there's been quite a bit of research on the best in-memory structure for minecraft-like worlds, and they're interesting to read. This is a good introduction.

User avatar
Soupspoon
You have done something you shouldn't. Or are about to.
Posts: 3390
Joined: Thu Jan 28, 2016 7:00 pm UTC
Location: 53-1

Re: Coding: Fleeting Thoughts

Postby Soupspoon » Mon Feb 05, 2018 5:25 pm UTC

(I'd just like to point out that, first of all, my battery is warning that it's very low, thus the low quality/consistency of my pseudocode once I got in a rush. But also that I mentioned Minecraft as an off-hand example of storage requirements, not knowing it was being used as graphical front-end by our frien, here. No link there, in my intent. And I'll consult your link, Tub, when I've got double digit battery percentage again (or, likely, when I'm back on a non-mobile connection, whilst chargung is going on as well). Don't mind me. Just thinking aloud! :P)

Tub
Posts: 381
Joined: Wed Jul 27, 2011 3:13 pm UTC

Re: Coding: Fleeting Thoughts

Postby Tub » Tue Feb 06, 2018 12:12 pm UTC

I stumbled over this special case again, so here's a riddle for you. Insert values into this JavaScript snippet to trigger the condition.

Code: Select all

var a = ...;
var b = ...;
var c = ...;
if (a == b && a == c && b != c)
  console.log("what?");

User avatar
Peaceful Whale
Posts: 159
Joined: Sun Jul 16, 2017 10:38 pm UTC
Location: Northern Virginia

Re: Coding: Fleeting Thoughts

Postby Peaceful Whale » Tue Feb 06, 2018 12:53 pm UTC

Tub wrote:I stumbled over this special case again, so here's a riddle for you. Insert values into this JavaScript snippet to trigger the condition.

Code: Select all

var a = ...;
var b = ...;
var c = ...;
if (a == b && a == c && b != c)
  console.log("what?");

???
What about the transitive property?
How is this possible?
Do we have to break the compiler or something?
My meta for future reference
Spoiler:
cemper93 wrote:Your meta appears to be "just writes whatever is on his mind and doesn't remember what happened more than five hours ago"

Mutex
Posts: 1324
Joined: Wed Jan 09, 2008 10:32 pm UTC

Re: Coding: Fleeting Thoughts

Postby Mutex » Tue Feb 06, 2018 12:59 pm UTC

Tub wrote:I stumbled over this special case again, so here's a riddle for you. Insert values into this JavaScript snippet to trigger the condition.

Code: Select all

var a = ...;
var b = ...;
var c = ...;
if (a == b && a == c && b != c)
  console.log("what?");

I thought the weird scenario that could happen is: a == b & b == c & a != c

User avatar
Soupspoon
You have done something you shouldn't. Or are about to.
Posts: 3390
Joined: Thu Jan 28, 2016 7:00 pm UTC
Location: 53-1

Re: Coding: Fleeting Thoughts

Postby Soupspoon » Tue Feb 06, 2018 1:15 pm UTC

Best guess, a, b, c cross loose type-bounds like a ring-species. Say maybe "0.0" != "0" as text but 0.0 == 0 as values, yet text of a value can get so (without checking) doing 0=="0.0" gives truth, 0="0" gives truth but "0.0"!="0". (Doesn't happen in Perl, they'd all be true-on-equal, even explicit "0"=="0.0". Its strength and weakness1.)

Next guess, the opposite direction. Something funny like NAN (does that exist in javascript?) that you might need to produce by doing a compound item in the assignment. There are things that do not equal themselves, but can be made to equal (sometimes via contrived means) other values.

Is it javascript-specific? Java-family? Possible further out amongst the wider C-like-ish clan, at least those not strongly typed?


1 -edit: To expand on that, using eq/ne instead of ==/!= does textual comparisons for textual accuracy, and a bit of leaway for defined-as-value. If we assign ($a,$b,$c)=(0,"0","0.0") then ($a eq $b) but ($a ne $c) as well as ($b ne $c). But this is neither the answer we need, actually surprising when you pomder it nor is it within the bounds of the puzzle. Just FYI.
Last edited by Soupspoon on Tue Feb 06, 2018 1:42 pm UTC, edited 1 time in total.

User avatar
Flumble
Yes Man
Posts: 1998
Joined: Sun Aug 05, 2012 9:35 pm UTC

Re: Coding: Fleeting Thoughts

Postby Flumble » Tue Feb 06, 2018 1:26 pm UTC

Transitivity holds when you use a true equality operator instead of ==. :roll:

Anyway, I got 42 (that can't be a coincidence; then again I didn't remove trivial 'duplicates') scenarios for which a = b, b = c, a ≠ c happens:

Code: Select all

       1     "0"   false      ""
       2     "0"   false      []
       3     "0"   false    [[]]
       4     "0"       0      ""
       5     "0"       0      []
       6     "0"       0    [[]]
       7      ""   false     "0"
       8      ""   false     [0]
       9      ""       0     "0"
      10      ""       0     [0]
      11      []   false     "0"
      12      []   false      []
      13      []   false    [[]]
      14      []   false     [0]
      15      []       0     "0"
      16      []       0      []
      17      []       0    [[]]
      18      []       0     [0]
      19      []      ""      []
      20      []      ""    [[]]
      21    [[]]   false     "0"
      22    [[]]   false      []
      23    [[]]   false    [[]]
      24    [[]]   false     [0]
      25    [[]]       0     "0"
      26    [[]]       0      []
      27    [[]]       0    [[]]
      28    [[]]       0     [0]
      29    [[]]      ""      []
      30    [[]]      ""    [[]]
      31     [0]   false      ""
      32     [0]   false      []
      33     [0]   false    [[]]
      34     [0]   false     [0]
      35     [0]       0      ""
      36     [0]       0      []
      37     [0]       0    [[]]
      38     [0]       0     [0]
      39     [0]     "0"     [0]
      40     [1]    true     [1]
      41     [1]       1     [1]
      42     [1]     "1"     [1]

Note that the elements come from three separate sets, so [0] from set one is not [0] from set two.

Code: Select all

//shame on javascript for not having concatMap :: [a] -> (a->[b]) -> [b]
Array.prototype.concatMap = function(f) {
    return this.map(f).reduce((acc,el) => acc.concat(el), []);
}

//elements from the marvelous "equality" table https://dorey.github.io/JavaScript-Equality-Table/
set1 = [true,false,1,0,-1,"true","false","1","0","-1","",null,undefined,Infinity,-Infinity,[],{},[[]],[0],[1],NaN]
set2 = [true,false,1,0,-1,"true","false","1","0","-1","",null,undefined,Infinity,-Infinity,[],{},[[]],[0],[1],NaN]
set3 = [true,false,1,0,-1,"true","false","1","0","-1","",null,undefined,Infinity,-Infinity,[],{},[[]],[0],[1],NaN]

res = set1.concatMap(a=>set2.concatMap(b=>set3.concatMap(c=> (a == b && b == c && a != c)?[[a,b,c]]:[])))

res.map((el, i) => [i+1].concat(el).map((val) => ("        "+JSON.stringify(val)).substr(-8)).join("")).join("\n")

Add an = to each comparison and suddenly the list is empty.

[edit]still had to modify to proper output
Last edited by Flumble on Wed Feb 14, 2018 11:19 am UTC, edited 2 times in total.

User avatar
Soupspoon
You have done something you shouldn't. Or are about to.
Posts: 3390
Joined: Thu Jan 28, 2016 7:00 pm UTC
Location: 53-1

Re: Coding: Fleeting Thoughts

Postby Soupspoon » Tue Feb 06, 2018 1:56 pm UTC

Aha. Further than "different types of numbers" but closer than "into the really esoteric stuff".

I occasionally use truth or falsity tests directly as 1 or 0 in mathematical constructs, so I might have guessed that. But, perlwise, ("0" == "") almost certainly complains (if warnings are used) about the "" being non-numeric, and a literal [0] or [1] is an Array reference treated in this regard as a specific non-blank string that wouldn't match anything else (even a neighbouring matching [0] or [1] not explicitly copied from the original).

But nice to know!

(As is the "use = instead of == in a test… Hey! What went terribly wrong?!?" common error. ;))

User avatar
Peaceful Whale
Posts: 159
Joined: Sun Jul 16, 2017 10:38 pm UTC
Location: Northern Virginia

Re: Coding: Fleeting Thoughts

Postby Peaceful Whale » Tue Feb 06, 2018 2:03 pm UTC

Question: what if i wanted to make the area expand as the cubes travel? But still have a max size, or maybe not.
My meta for future reference
Spoiler:
cemper93 wrote:Your meta appears to be "just writes whatever is on his mind and doesn't remember what happened more than five hours ago"

User avatar
Peaceful Whale
Posts: 159
Joined: Sun Jul 16, 2017 10:38 pm UTC
Location: Northern Virginia

Re: Coding: Fleeting Thoughts

Postby Peaceful Whale » Tue Feb 06, 2018 2:08 pm UTC

Soupspoon wrote:But what I meant by finite-but-boundless is just how it treats the edges. For X/Y/Z of 0..24, the 'upper' neighbour of 24 is 0, and the 'lower' neighbour of 0 vice-versa. That'd be in your raw code, doesn't matter how it then gets rendered.

Pseudocode (maybe some Perlish elements, though I was aiming for generic C-family so ignore them), made flexible:

Code: Select all

define SIZE=25;

sub TrueVal(n) {
  if n<0 return n+SIZE;
  if n>=SIZE return n-SIZE;
  return n;
  // Doesn't handle going over the 0 or SIZE-1 limits by more than SIZE elements.
  // Recurse or loop until you are returning 'n' unchanged, perhaps?
  // You can also do things with modulous, as long as you correct/avoid bad behaviour in the negatives.
}
sub NeighboursOf(x,y,z) {
  Tally=0; // for later
  for (dX=-1; dX<=1; dX++) {
    for (dY=-1; dY<=1; dY++) {
      for (dZ=-1; dZ<=1; dZ++) {
        AssessedCell=Assess(TrueVal(x+dX),TrueVal(y+dY),TrueVal(z+dZ));
        // Then, however you'd prefer, add the signums (negative numbers made positive, zero is zero) of (dX, dY, dZ) together.
        // Total=3: corner neighbour (share vertex, ignore in your case)
        // Total=2: edge neighbour (share edge, add 0.5*AssessedCell to your tally)
        // Total=1: face neighbour (share face, add 1*AssessedCell to your tally)
        // Total=0: original cell (ignore? Or use to decide if it's a born/live/die/stay-dead situation.)
        // Total=anything else, fatal error. Ought to be impossible, but catch it anyway!
        TallyResult=Foo(Bar(Baz(Tally, Status(x,y,z)))); // Whatever.
        return TallyResult;
      }
    }
  }
}


Is this how?
(I understand this *kinda*)
Would I just use this?
Is there a different way?
Could I make it so it’s always the smallest array possible? Or just 3 bigger?
My meta for future reference
Spoiler:
cemper93 wrote:Your meta appears to be "just writes whatever is on his mind and doesn't remember what happened more than five hours ago"

User avatar
Peaceful Whale
Posts: 159
Joined: Sun Jul 16, 2017 10:38 pm UTC
Location: Northern Virginia

Re: Coding: Fleeting Thoughts

Postby Peaceful Whale » Tue Feb 06, 2018 2:09 pm UTC

(I am a noob, and definitely need some help here)
My meta for future reference
Spoiler:
cemper93 wrote:Your meta appears to be "just writes whatever is on his mind and doesn't remember what happened more than five hours ago"

User avatar
Soupspoon
You have done something you shouldn't. Or are about to.
Posts: 3390
Joined: Thu Jan 28, 2016 7:00 pm UTC
Location: 53-1

Re: Coding: Fleeting Thoughts

Postby Soupspoon » Tue Feb 06, 2018 5:08 pm UTC

Peaceful Whale wrote:Is this how?
(I understand this *kinda*)

It's one way of doing one thing. It might not be the thing you want to do, and it might not be the exact way you'd want to do the thing. You could perhaps make the call to Assess(x, y, z) check-and-correct the out of range (with a TrueVal() function) before passing to RealAssess(validX, validY, validZ) so as to not bother your function. Also, instead of dX going from -1 to 1, and offsetting the 'core' X, you could do a lookX that runs from (X-1) to (X+1) and do the 'is it corner, edge, face or core?' by direct check of whether lookX==coreX, lookY==coreY, lookZ==coreZ, but that's going to be an eight-leafed triple-branching check such as (I think!):

Code: Select all

if(equalX)then(if(equalY)then(if(equalZ)then(is_core)else(is_face))else(if(equalZ)then(is_face)else(is_edge)))else(if(equalY)then(if(equalZ)then(is_face)else(is_edge))else(if(equalZ)then(is_edge)else(is_corner)))

...insert whitespace to taste, as you go. ;)

Thus I quite like the dX,dY,dZ way of doing this kind of thing, as a way of extracting and combining the unit disolacements to determine the Manhattan Distance from the origin to the check-coords.

And then I made an obvious error. Please note this as you transcribe it. I couldn't recall what the signum function was, in Python. (Look for signum(), sgn() or sign() functions/methods. It's a neat monolithic way of getting +1, 0 or -1), and what I then meant to write was that signum(x)*x would give 1 for x=±1, zero for zero, to add to the similar results for y and z, giving 0 total at the core cell, 1in total at a face-on-face neighbour (six of them), 2 for edge-centres (12 of them) and 3 for the corners (8 of those, bringing the total to the 27 you'd expect).

(If you do this correctly, you can also plan to use this for (beyond your scope, but worth considering) next-to-neighbour assessment (dX=-2..+2) if you wanted, as signum(-2)*(-2)=>+2 (two away from origin, regardless of direction, and the reason I was doing signum*original at all, rather than just using the signum) and classify weightings in a useful manner for all 125 cubes in a up-to-2-distance offsetting on the origin cubes.)

And then I realised that I'd completely overcomplicated things. Look for an abs() function, 'absolute'. That makes -n straight into n. Doesn't need sgn(). Doh! But now you see where I was going, in a rush as the battery rapidly depleted. :P

In fact, given you're only going ±1 from the origin, just do a square. dX*dX (etc). ±1 => +1 and 0 => 0, without fuss. It's only values beyond 1 (either sign) or non-zero fractions of 1 that this might be wrong for your purposes, but those don't apply to you!

Would I just use this?
By the Gods, absolutely not! I did my best to make it easier to translate my pseudocode to the Python than if I'd written it in valid Pascal, Ada, Perl, COBOL, etc, which I would have had more confidence in. ;) You need to run through the lines and assume they are all comments, then rewrite tye bits in your own favourite style of actual Python. (Noting the above.)

Is there a different way?
Always! I'm not even saying that the above way is the best way. It's one I'd favour, off the bat, but testing and development might force a rewrite because of an issue. Whether that be merely style, flexibility or because I've erred. Like I might have done, had I been doing the live programming myself!

Could I make it so it’s always the smallest array possible? Or just 3 bigger?

I'm not entirely sure what you mean by this. In a wrap-around 'world', the array is the size it is (change it, and you shoehorn cells in there, between neighbours to make them no longer neighbours).
If you're doing "move the edges out before they become significant" so that you have effectively infnite space, only not frommthe start, you need (at the simplest) to tack on a test each time a cell is set as 'live' to make sure that once you get to xmax (or within a decent range of it) you resize/reallocate the array to give you a new higher xmax to move into. Same with y and z, and ditto with x/y/zmins at the lower limit.

Beware 'explosions'. Even if you also regularly track deaths (and no births) of cells to raise your min values and lower your max ones, if you've got a pattern that sends elements out in all directions (even if it leaves the centre and most of the other directions devoid of live cells) the array will just resize larger and larger and larger. By doing a 'smart review' you might be able to identify a fragment travelling right+forward+up (with no 'debris' left behind) and a fragment travelling left+backwards+down (ditto) that can each be self-contained in their own very small box. But that's part of the "dictionary store of references to arrays" thing that I'm not sure I explained properly. (Sort of mentioned along the way in Tub's link, an interesting read indeed, but that won't help you.)

It's why I thought you might prefer the wrap-around (static) array. Simpler, though functionally different from the version without wrap-around, just ever expanding shoulder-room whilstsoever required.

User avatar
Peaceful Whale
Posts: 159
Joined: Sun Jul 16, 2017 10:38 pm UTC
Location: Northern Virginia

Re: Coding: Fleeting Thoughts

Postby Peaceful Whale » Tue Feb 06, 2018 7:52 pm UTC

...
I really like the idea of contains traveling ones in their own little arrays...
I could give the arrays XYZ values...

This sounds really hard though... I could make a function that checks and sees how far away a cell is from other cells... but clump of cells? How far away it is from another clump?

How would one go about doing this?
My meta for future reference
Spoiler:
cemper93 wrote:Your meta appears to be "just writes whatever is on his mind and doesn't remember what happened more than five hours ago"

User avatar
Soupspoon
You have done something you shouldn't. Or are about to.
Posts: 3390
Joined: Thu Jan 28, 2016 7:00 pm UTC
Location: 53-1

Re: Coding: Fleeting Thoughts

Postby Soupspoon » Tue Feb 06, 2018 9:42 pm UTC

(As long as you realise that we're talking about specific and possibly theoretical patterns, discovered or designed to do this and that most configurations of even a sympathetic and enabling 3DConwayGoL setup aren't going to be quite so neat...)

The simplest, most naive way would be to have a set of data-objects (themselves in a basic array, a linked list, whatever floats your boat) with first of all a fairly tight and centred-on-your-Glider standard 3D array, and secondly three offsets for XYZ. As the glider-thing moves within its 'cage', your simulation checks where within the array this next step of the glider is now placed, and if it finds that it is off-centre, it shuffles it back to the centre (by whichever unit x, y and z displacements it deems necessary) and then it adds the removed position onto the cage-array's associated XYZ (which presumably is tracking the absolute XYZ of the centre-of-cage cell, which may be 0,0,0 as far as the cage itself is concerned), so that if it is deemed that a set of cells move 1 cell in the X direction and -1 in the Z direction, within the cage you shuffled everything to x-- and z++ while using X++ and Z-- on the cage's associated information.


You need to get to know how to handle more complex data records. In the old days, you'd do something like "define record Cage= field:array(5,5), X:int, Y:int, Z:int" or somesuch. In strict object-orientated definitions, you'd define a class of Cage with a field array and X, Y, Z elements as public.

A quick-and-dirty way for a type-loose language is just to make an array of four elements, the first element being further the array of array of array that is the cage/field/whatever construct (the thing you actually came here to learn about, if you recall ;)) and the second, third, fourth elements can store your XYZ values.

If you do the Q&D way, it's possible to just directly refer to Cage[0][3][-1][0] for the element 3,-1,0 of the 'travelling cage' and Cage[2] would be the Y displacement, but writing that acurately all over the place is liable to all kinds of errors, so create reading and writing subs that are the only non-test accessors of the very buried data, check they do it right (with those test/debug methods, removed/commented-out once validated to sufficient satisfaction) and then only use these. e.g. something you could call with CheckCell(CageRecord, X, Y, Z) that looks at the Cage for the cage-stored displacements, adjusts the X, Y, Z with them to get the to 0,0,0-centred equivalnt for the cage and then examines the Cage's array³ item for the actual cell.

You'd also need a 'collision check' between cages (to see if they were close enough to interact), a method of merging cages (a new cage with an array-thing sized to hold the two collisioning cages, and its own XYZ offsets being worked out afresh from the actual absolute XYZ that this new cage's centre must have) and of course functions to identify splitable cages (where there's a clear planar gap, between parts of an existing single cage) and then split them (subsetting into smaller arrays, recalculating each of the associated XYZs as a reverse of the merge function) because that is how you get multiple independent cages out of your initial 25x25x25 setup, or whatever size it has managed to bloat/shrink to through basic border-management of the original.

This is a complicated thing to do. Even to think of. If I could quickly scribble some diagrams to illustrate what I mean, I'm sure it would be far better than all these words I'm using.

And also: Maybe something to think about later, not right now. Do your original project, first. Get the hang of the array access, for a start.

And also also: I still do not claim that it's the absolute best way of doing this complicated thing, and it might not even be in the top ten, but I'm laying it out there as theory, based upon experiences in unrelated but relatable coding problems I have worked on. (It is from those, mostly, that my record/class/irregular-deep-layered-array alternate methods arise. Whatever you do, add copious comments to explain things when you make a seemingly arbitrary decisision on how you pack your data. It helps people with less than a full familiarity of the project, which includes "you, diving back in after a few weeks doing something else, and now wondering what everything does".)

User avatar
Peaceful Whale
Posts: 159
Joined: Sun Jul 16, 2017 10:38 pm UTC
Location: Northern Virginia

Re: Coding: Fleeting Thoughts

Postby Peaceful Whale » Tue Feb 06, 2018 9:48 pm UTC

Ok: get the thing itself working.
Then add cool stuff.
My meta for future reference
Spoiler:
cemper93 wrote:Your meta appears to be "just writes whatever is on his mind and doesn't remember what happened more than five hours ago"

Tub
Posts: 381
Joined: Wed Jul 27, 2011 3:13 pm UTC

Re: Coding: Fleeting Thoughts

Postby Tub » Tue Feb 06, 2018 10:46 pm UTC

I'd say that Flumble got it, but there's something wrong with that list. For example:
> 2: ["0", false, [1]]
b == c doesn't hold, because false == [1] is false. There are other examples involving [1] that appear wrong.


The gist however is that type coercion in JavaScript is weird, and Flumble successfully made that point.

Things like ["42.0", 42, "42"] also work. Both strings are equal to the number, but not equal to each other.

Or try these three:

Code: Select all

var a = new Boolean(false);
var b = Boolean(false);
var c = new Boolean(false);

Quick, which of these are equal? If you needed to look it up or run the code, then congratulations, you're still sane.

Note that neither is equal to

Code: Select all

var d = Boolean(new Boolean(false));

because obviously d === true.

There's one more case that's even sneakier. Worry no more about transitivity. You can solve this:

Code: Select all

var a = ...;
var b = ...;
if (a == b && a != b)
  console.log("seriously?");

User avatar
Flumble
Yes Man
Posts: 1998
Joined: Sun Aug 05, 2012 9:35 pm UTC

Re: Coding: Fleeting Thoughts

Postby Flumble » Tue Feb 06, 2018 11:41 pm UTC

Peaceful Whale wrote:Ok: get the thing itself working.
Then add cool stuff.

Note that, as long as you don't have more than a couple of tens of thousands of live cells, you could use the dictionary/set approach suggested earlier: put the coordinates of live cells in a tuple (x,y,z) and add it to the set and remove it if the cell dies. Since adding, removing and testing existence takes about constant time, it shouldn't slow down too much when you get lots of living cells. And the overhead of a set isn't all that extreme.

The greatest advantage is that you can write short, readable code for an infinite grid. :D It may waste memory compared to an algorithm that checks for and optimizes patterns in the simulation, but it's much easier to .pop() random cells once you hit 100MB of memory than to write such advanced algorithms.

Tub wrote:I'd say that Flumble got it, but there's something wrong with that list. For example:
> 2: ["0", false, [1]]
b == c doesn't hold, because false == [1] is false. There are other examples involving [1] that appear wrong.

Oops, I beautified it manually because I feared some conversions in JSON.stringify would be lossy (like undefined turning into null), but Array(0) is of course an empty array, not an array containing a zero. :oops:

Tub wrote:There's one more case that's even sneakier. Worry no more about transitivity. You can solve this:

Code: Select all

var a = ...;
var b = ...;
if (a == b && a != b)
  console.log("seriously?");

It seems I can't. I'd guess it's some floating point number.

User avatar
hotaru
Posts: 1040
Joined: Fri Apr 13, 2007 6:54 pm UTC

Re: Coding: Fleeting Thoughts

Postby hotaru » Wed Feb 07, 2018 12:16 am UTC

Tub wrote:There's one more case that's even sneakier. Worry no more about transitivity. You can solve this:

Code: Select all

var a = ...;
var b = ...;
if (a == b && a != b)
  console.log("seriously?");

Code: Select all

var a = 0;
var b = {v: 0, valueOf: function(){return this.v++}}; 

Code: Select all

factorial product enumFromTo 1
isPrime n 
factorial (1) `mod== 1

Tub
Posts: 381
Joined: Wed Jul 27, 2011 3:13 pm UTC

Re: Coding: Fleeting Thoughts

Postby Tub » Wed Feb 07, 2018 9:36 am UTC

Points to hotaru for this one. When comparing an object to a native value, javascript will first try to "unbox" the object, which is why new Boolean(false) == false and 42 == [42]. Unboxing may also include calling valueOf() or toString().

But you don't need unboxing. You don't need 'a' to be an object. You don't even need type coersion. See?

Code: Select all

if ((typeof a === 'number' || typeof a === 'string') && a === a && a !== a)
   console.log("That's it, I quit");

(Hint: there are no weird floating point values involved.)

Demki
Posts: 199
Joined: Fri Nov 30, 2012 9:29 pm UTC

Re: Coding: Fleeting Thoughts

Postby Demki » Wed Feb 07, 2018 7:01 pm UTC

Assuming this is the global object(window or global):

Code: Select all

(function() {
  function factorial(n) { // or any function such that f(0)=f(1) and f(2)/=f(3)
    let res = 1;
    for(let i = 2; i <= n; ++i) res *= i;
    return res;
  }
  let something = 4;
  Object.defineProperty(this, 'a',
    { get()
      {
        let res = factorial(something);
        something = (something + 1) % 5;
        return res;
      }
    });
})();
if ((typeof a === 'number' || typeof a === 'string') && a === a && a !== a)
   console.log("That's it, I quit");


You can come with the pitchforks now.

Tub
Posts: 381
Joined: Wed Jul 27, 2011 3:13 pm UTC

Re: Coding: Fleeting Thoughts

Postby Tub » Wed Feb 07, 2018 8:05 pm UTC

Yeah, that's the idea. a is no longer a local variable, but a a global variable, i.e. property of the global object. Properties can have getters!

Getting the global object in a compatible way is tricky, but possible: call a function without a context, then it'll use the global object as 'this'. Except in strict mode, so make sure the function doesn't run in strict mode:

Code: Select all

var ref_to_global = Function('return this')();


A nice piece of code you can write is thus:

Code: Select all

var ref_to_global = Function('return this')();
Object.defineProperty(ref_to_global, "undefined", {
   get: function() {
      var undef;
      return Math.random() > 0.1 ? undef : true;
   },
   enumerable: false
});

You could just create a global variable, but that's too easy to debug. Cookies to everyone who manages to sneak this into a popular npm package!

User avatar
Peaceful Whale
Posts: 159
Joined: Sun Jul 16, 2017 10:38 pm UTC
Location: Northern Virginia

Re: Coding: Fleeting Thoughts

Postby Peaceful Whale » Fri Feb 09, 2018 3:44 pm UTC

For the rotation function, I’m doing a bunch of 3D sine, cosine, and tangent stuff... that way you can rotate the image with the mouse...
It’s a good thing we just learned about stuff like this in geometry...
It’s kinda pretty, but I made an error in the code... so now it only spins one way... I figured out what’s wrong and now it works nicely.
My meta for future reference
Spoiler:
cemper93 wrote:Your meta appears to be "just writes whatever is on his mind and doesn't remember what happened more than five hours ago"

User avatar
Peaceful Whale
Posts: 159
Joined: Sun Jul 16, 2017 10:38 pm UTC
Location: Northern Virginia

Re: Coding: Fleeting Thoughts

Postby Peaceful Whale » Wed Feb 14, 2018 2:33 am UTC

So: I’ve got most of my stuff wrote out, and I’m testing little batches...
however when I do I get this error:
“List Index out of Range”
My 3D Array is formed fine, it is filled fine, however when it is scanned, it through that error.
This section of code is where it is happening...

Code: Select all


cubes_old = []
max_x, max_y, max_z = 10
min_x, min_y, max_z =-10

for x in range(min_x, max_x):
*tab* for y in range(min_y, max_y):
*tab* *tab* for z in range(min_z, max_z):
*tab* *tab* *tab* cubes_old[x][y][z] = 1

if cubes_old[1][2][3] == 1:
*tab* print("1")

Replace *tab* with actual tabs of course... the error is from the if cubes_old == 1 thug. No matter what cell I tell it to check it throws that error. I feel like this is a really nooby mistake, and would appreciate help.

This isn’t the full code, I trimmed out the unnecessary stuff, however if I run this code it still gives me the error...
My meta for future reference
Spoiler:
cemper93 wrote:Your meta appears to be "just writes whatever is on his mind and doesn't remember what happened more than five hours ago"

User avatar
Sizik
Posts: 1205
Joined: Wed Aug 27, 2008 3:48 am UTC

Re: Coding: Fleeting Thoughts

Postby Sizik » Wed Feb 14, 2018 2:58 am UTC

Have you tried sprinkling in some print statements to verify which array indices are actually being assigned?
gmalivuk wrote:
King Author wrote:If space (rather, distance) is an illusion, it'd be possible for one meta-me to experience both body's sensory inputs.
Yes. And if wishes were horses, wishing wells would fill up very quickly with drowned horses.

User avatar
Soupspoon
You have done something you shouldn't. Or are about to.
Posts: 3390
Joined: Thu Jan 28, 2016 7:00 pm UTC
Location: 53-1

Re: Coding: Fleeting Thoughts

Postby Soupspoon » Wed Feb 14, 2018 5:38 am UTC

The usual error *I* make (if I translate code between languages and forget the differences between the two) is to try to access the nth element of a [0..n-1] array, or the 0th item of a [1..n] array. Obviously Python is so loosely typed that it works for either as long as you nudge the array to cover where you're expecting.

However, I note in reading your sample (I assume the "*tab*" is your indents... Code-tag usually preserves spaces, which ought to do much the same, I think, as a tabbing indent) that you have max_z in both the +10 (maxes) and -10 (mins) assignment lines. Gets set as +10, then reset as -10 whilst min_z doesn't get set at all.

Could it (in the absence of a previously defined min_z) end up trying to do a 'z' in range (undefined|zero to -10), which a [..][..][3] reference is obviously outside, pretty much however Python parses the erroneous ranging.

That's if the error is in your original code, that is, and not actually your transcription over to here. Which is also easily possible but then leaves the original error as almost unaswerable at present. ;)


(Adding the appropriate format of printing "Now setting Foo to value "+Foo+"!" to strategic points will reveal this kind of thing, as suggested. I tend to maintain a 'portable debugging-line' that I move and copy around the shop, just as much as needed. Sometimes I go so far as to set a global DEBUG_LEVEL variable and then something like if DEBUG_LEVEL>5 then print "FuncAddItAll: Currently adding "+new_figure+" to "+running_total; or somesuch, which I can switch on and off, according to the detail I need. Then, at or near the end of testing a section, search for all lines with DEBUG_LEVEL mentioned and delete some or all of them when I'm cleaning up afterwards. But I'd be just as happy to comment the more basic version of the lines out, once I think I'm happy enough with what I'm being told, but it then lets me uncomment them again if I get a pang of renewed uncertainty after a later run-time error or other surprise.)

speising
Posts: 2254
Joined: Mon Sep 03, 2012 4:54 pm UTC
Location: wien

Re: Coding: Fleeting Thoughts

Postby speising » Wed Feb 14, 2018 7:23 am UTC

copy&paste considered harmful

commodorejohn
Posts: 1084
Joined: Thu Dec 10, 2009 6:21 pm UTC
Location: Placerville, CA
Contact:

Re: Coding: Fleeting Thoughts

Postby commodorejohn » Wed Feb 14, 2018 7:54 am UTC

Arrays considered harmful...
"'Legacy code' often differs from its suggested alternative by actually working and scaling."
- Bjarne Stroustrup
www.commodorejohn.com - in case you were wondering, which you probably weren't.

User avatar
chridd
Has a vermicelli title
Posts: 818
Joined: Tue Aug 19, 2008 10:07 am UTC
Location: ...Earth, I guess?
Contact:

Re: Coding: Fleeting Thoughts

Postby chridd » Wed Feb 14, 2018 9:51 am UTC

I get an error here:
Peaceful Whale wrote:

Code: Select all

max_x, max_y, max_z = 10
min_x, min_y, max_z =-10
because you can't assign one thing to three variables like that. Either

Code: Select all

max_x, max_y, max_z = 10, 10, 10

or

Code: Select all

max_x = max_y = max_z = 10

(the latter assigns all the variables to the same value; the former lets you put different values there). (And as previously mentioned, you have max_z instead of min_z.)

If I fix that, then this:

Code: Select all

for x in range(min_x, max_x):
   for y in range(min_y, max_y):
      for z in range(min_z, max_z):
         cubes_old[x][y][z] = 1
gives me an error, because cubes_old[x] isn't assigned to anything yet. A 3-dimensional array is an array of arrays of arrays, but you have to make all those arrays yourself; that's where this code is useful.

Finally, array indexes can't be negative; Python interprets a[-1] as meaning the last element of a, a[-2] means the second-to-last element, etc. Therefore, even if your code did work, you'd likely run into bugs where multiple numbers end up referring to the same array element. Either start at 0, or use dictionaries instead of arrays. (If you use dictionaries, you can use tuples as keys, i.e. cubes_old[x,y,z], and then you won't have to worry about the problem I mentioned in the previous paragraph.)
~ chri d. d. /tʃɹɪ.di.di/ (Phonotactics, schmphonotactics) · she(?)(?(?)(?))(?(?(?))(?))(?) · Forum game scores
mittfh wrote:I wish this post was very quotable...
flicky1991 wrote:In both cases the quote is "I'm being quoted too much!"

speising
Posts: 2254
Joined: Mon Sep 03, 2012 4:54 pm UTC
Location: wien

Re: Coding: Fleeting Thoughts

Postby speising » Wed Feb 14, 2018 10:07 am UTC

the nice thing in python is also, when you do it on the command line, you can just write

Code: Select all

cubes_old

after the loops, and it spits out it's value so you can check it.

(stepping through with a debugger would be even nicer, obviously)

and another thing:
the error is from the if cubes_old == 1 thug.


it's actually (well, most likely, if we make the code up to there runnable at all) from

Code: Select all

cubes_old[x][y][z] = 1

another reason to try this interactively line by line.

User avatar
Peaceful Whale
Posts: 159
Joined: Sun Jul 16, 2017 10:38 pm UTC
Location: Northern Virginia

Re: Coding: Fleeting Thoughts

Postby Peaceful Whale » Wed Feb 14, 2018 11:07 am UTC

Ok, thank you...
I did originally have each variable declare separately, (min_x =10... etc) but when I put it here, I made it different...
The no negative numbers in arrays is going to be annoying... I was trying to make it expandable, but then I’d have to move it from only 3 sides of the cube array... ad then have to move all of the cubes so they’re centered...?
I will fix stuff, thanks for your help!
My meta for future reference
Spoiler:
cemper93 wrote:Your meta appears to be "just writes whatever is on his mind and doesn't remember what happened more than five hours ago"

User avatar
phlip
Restorer of Worlds
Posts: 7550
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: Coding: Fleeting Thoughts

Postby phlip » Wed Feb 14, 2018 11:18 am UTC

As noted, it does look like you've re-typed your code here in the forum, rather than copy-pasting the code you're actually trying to run, and I think in the process of re-typing it there's been some typos introduced. So it's hard to tell exactly what errors are contributing to the bug you're experiencing, and what are just transcription errors.

So there are any number of things your problem might be, but we'd have a much better shot at decyphering the error if you copy-pasted the actual code you're trying to run.

With that said, I'm going to ignore the more typographical things (assigning to the wrong variable, weird broken assignment syntax, strange indenting) and look at the sort of things that are more likely to be the actual problem.

First: list indexes start at zero, and count up. If you want to represent starting from -10, you'll need to do something like add 10 to the indexes whenever you look them up in the list. Same as the C that, as I understand it, you're familiar with.

Second: The set-item statement, "thing[index] = stuff" only works if that slot in the list exists. So, for example, if you have a list that's five entries long, you can assign to thing[0] through thing[4], but if you try to assign to thing[5] you will get an IndexError. So, in your code, you make an empty list, which contains zero items... so trying to assign to any index will give you an IndexError. There are methods to change the size of lists, append items, etc, but I'm not going to go into much detail about them here since you probably don't actually want that, as I understand it you're more after one big statically-sized array. But this is why a lot of the examples people posted before on how to make a big 3D array did things that would construct a big list-of-lists that already was filled up, even if it's just filled up with meaningless values like 0 or None.

[edit] I see I've been beaten to the punch on most of these points. But still.

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

Ciber
Posts: 123
Joined: Fri Mar 15, 2013 1:33 pm UTC

Re: Coding: Fleeting Thoughts

Postby Ciber » Wed Feb 14, 2018 11:25 am UTC

Lately I have been working on force directed graph layouts. Currently trying to port (is that the right word here?) my naive implementation to numpy because with the 400 node, 900 link test graph I'm using it takes several seconds per iteration.

User avatar
Xanthir
My HERO!!!
Posts: 5292
Joined: Tue Feb 20, 2007 12:49 am UTC
Location: The Googleplex
Contact:

Re: Coding: Fleeting Thoughts

Postby Xanthir » Wed Feb 14, 2018 5:53 pm UTC

A further error - array indexes are 0 or larger. If you use negative indexes, in Python it doesn't refer to another item to the "left" of the 0th item, it instead starts counting from the *end* - -1 is the last element, -2 is the second from last, etc.

If you need arbitrary coordinates, you want to use one of the models people have talked about previously, where you're using a dict, rather than an array.
(defun fibs (n &optional (a 1) (b 1)) (take n (unfold '+ a b)))

User avatar
Peaceful Whale
Posts: 159
Joined: Sun Jul 16, 2017 10:38 pm UTC
Location: Northern Virginia

Re: Coding: Fleeting Thoughts

Postby Peaceful Whale » Wed Feb 14, 2018 6:17 pm UTC

Ok stuff is fixed, and *working* now. At least that part...

How would I add dictionary references?
I don’t understand how I would use a dictionary...
They’re like a dress books right? Name gives you a value... how Orel I add names and values? Would it make more sense?
My meta for future reference
Spoiler:
cemper93 wrote:Your meta appears to be "just writes whatever is on his mind and doesn't remember what happened more than five hours ago"


Return to “Coding”

Who is online

Users browsing this forum: No registered users and 6 guests