Wednesday, September 2, 2015

Eloquent Javascript Chapter 6 Table Layout Example

 Hello everyone! :)
Here are some notes I typed up to help you guys understand the beginning of the Table Layout example in chapter 6 of eloquent javascript.
This isn't the best worded thing in the world, but I believe if you work through it things will click and you will understand what is going on.

This is a reaaaally long-winded explanation of it all, but hopefully it is helpful :)

Enjoy!

NOTE: THIS CODE WAS DESIGNED TO BE READ IN A CODE EDITOR LIKE TEXTWRANGLER OR IN THE INTERACTIVE PROMPT AT http://eloquentjavascript.net/06_object.html

THE TABLES I PRINTED OUT FOR REFERENCE DO LINE UP PROPERLY ON BLOGGER


/*
var exampleData = [ //layed out in rows
    [    //row one (really row 0, etc)
     TextCell{text: ["##", "__"]},//the rows contain TextCell objects which contain the text
     TextCell{text: ["  "]},
     TextCell{text: ["##", "__"]},//if there are two text chunks that represents a height of 2
     TextCell{text: ["  "]},
     TextCell{text: ["##", "__"]}],
    [   //row two
     TextCell{text: ["  "]},
     TextCell{text: ["##", "__"]},
     TextCell{text: ["  "]},
     TextCell{text: ["##", "__"]},
     TextCell{text: ["  "]}],   
    [  //row three
     TextCell{text: ["##", "__"]},
     TextCell{text: ["  "]},
     TextCell{text: ["##", "__"]},
     TextCell{text: ["  "]},
     TextCell{text: ["##", "__"]}],
    [
     TextCell{text: ["  "]},
     TextCell{text: ["##", "__"]},
     TextCell{text: ["  "]},
     TextCell{text: ["##", "__"]},
     TextCell{text: ["  "]}],   
    [
     TextCell{text: ["##", "__"]},
     TextCell{text: ["  "]},
     TextCell{text: ["##", "__"]},
     TextCell{text: ["  "]},
     TextCell{text: ["##", "__"]}]
];

name         height country
------------ ------ -------------
Kilimanjaro    5895 Tanzania
Everest        8848 Nepal
Mount Fuji     3776 Japan
Mont Blanc     4808 Italy/France
Vaalserberg     323 Netherlands
Denali         6168 United States
Popocatepetl   5465 Mexico
 */

var exampleData = [
    [   
     new TextCell("##\n__"),
     new TextCell("  "),
     new TextCell("#u#\n_o_"),
     new TextCell("  "),
     new TextCell("##\n__")],
    [ 
     new TextCell("  "),
     new TextCell("##\n__"),
     new TextCell(".."),
     new TextCell("##\n__"),
     new TextCell("  ")],   
    [   
     new TextCell("##\n__"),
     new TextCell("  "),
     new TextCell("#u#\n_o_"),
     new TextCell("  "),
     new TextCell("##\n__")],
    [  
     new TextCell("  "),
     new TextCell("##\n__"),
     new TextCell(".."),
     new TextCell("##\n__"),
     new TextCell("  ")],   
    [   
     new TextCell("##\n__"),
     new TextCell("  "),
     new TextCell("#u#\n_o_"),
     new TextCell("  "),
     new TextCell("##\n__")]
  ];

/*
  The idea behind this is that it returns an array of RowHeights
  So it reduces each row of TextCells to 1 value: the minimum RowHeight
  (which really means the largest row height: the maximum of the rows,
   but the minimum you need to make the row the right size when drawing)
   (i.e. if you have a row of objects of different sizes, the minimum size(height)
    of the row is the largest size of any of those objects, right?)
  So let's break it down
   
    It starts off with rows.map()
      This means it is turning each row into some piece of info about the row
      (i.e. it is mapping each row to the "minimumHeight" that row can be to
       represent TextCell correctly (i.e. a two line hight textcell can't be
        represented with a one cell high row))
   
      Then it uses row.reduce()
        It is RETURNing row.reduce()'s result.
        This is because it is mapping the row itself to the result of the reduce
        Reduce takes two arguments (max, cell).
        Now reduce usually takes the first element, and the next element in the
        array as arguments.
        However, if you look at the code, it has
          return Math.max(max, cell.minHeight());
        Hmm you think, 'max' is a TextCell object.
        Thus it should fail in Math.max, since max() is a numeric function
       
        However, if it was coded as
          return Math.max(max.minHeight(), cell.minHeight());
        Then on the second attempt at reducing we would have
          return Math.max( (previous numeric result).minHeight(), cell.minHeight());
        "WAIT!" you think, the previous result is a number!
        Thus the next call to "max.minHeight()", using the prior result, would fail.
        Numbers don't have a minHeight method.
        What we really want to do is compare that prior max number with the next
        cell.minHeight.
       
        So what do we do?
        That is where the second argument to reduce() comes in.
       
        If you noticed, the Eloquent code has the following structure
          row.reduce(function(max,cell){ //code }, 0);
        See that zero?
        That is the default first 'max', or current element.
        What this means is that the reduce uses that as the first 'max'
        and uses the first element of the row array as the current 'cell'.
        I.e.
        The first time it runs it will do:
          return Math.max( 0, cell.minHeight());
          //cell is row[0], NOT row[1] like it normally would be.
        This fixes both issues we had with our earlier attempts!
        Because the next time it will still use return Math.max(max, cell.minHeight)
        only now max will always be a number and never a TextCell object!
        Success!
*/
function rowHeights(rows) {
  return rows.map(function(row) {
    return row.reduce(function(max, cell) {
      return Math.max(max, cell.minHeight());
    }, 0);
  });
}

//The example below prints out all 2 because the minimum height is 2 "##\n__" => "##", "__" (two lines!)
console.log(rowHeights(exampleData));


/* Alright, let's check out this one.
   For reference, if we printed out drawTable(exampleData) we would get:
  
        ##    #u#    ##
        __    _o_    __
           ## ..  ##  
           __     __  
        ##    #u#    ##
        __    _o_    __
           ## ..  ##  
           __     __  
        ##    #u#    ##
        __    _o_    __
  
   carefully notice the 3rd column, see how it has a width of 3 but the ".." element
   has a width of 2? (in our actually code definition of it
     new TextCell(".."), //<- br="" not="" of="" three="" two="" width="">   This is where the rest of this explanation comes in.
   This is what cellWidths is all for, the padding and alignment of the columns
   with their subcolumns.
  
   The idea behind this one is a bit trickier.
   I am just going to phrase it bluntly, which will make little sense at first,
   and then I am going to break it down so it makes sense.
  
   It will help to know what the output of this is.
   It will return an array of values, just like rowHeights, which represent the
   maximum column widths of a given column
   So, in my example, I purposely made the third column alternate between "#u#\n_o_"
   and ".."
   In the first one we would get
     #u#
     _o_
   Upon printing it out. This column has a width of 3 characters, so it has a width of 3.
   But upon printing the one out just below it we would get
     ".."
   This column has a width of 2, not 3.
   This means that at least two layers of the same overall column have different widths!
     //3rd column
     #u#
     _o_
     ..//width of 2, doesn't match the width of the other pieces
     #u#
     _o_
     ..//width of 2, doesn't match the width of the other pieces
     #u#
     _o_
   Thus, to find out what the minimum width a column needs to be to draw it all correctly
   colWidths maps the place of this column to the "minimum" width needed.
   By place I mean, the output of colWidths is
     [col1's minimum width, col2's minimum width, col3's min width, etc]
   As you can probably imagine in your mind's eye,
   This array is like smooshing the entire table into a flat disk,
   where each slot in the disk corresponds to the largest width of that corresponding
   column.
  
  
   (Note that the minimum width needed to draw a column is the maximum of the subcolumns
    themselves. Minimum needed to draw right, maximum of the subpieces)
  
   So, what this means is, if we ran
     console.log(colWidths(exampleData));
     //-> [2,2,3,2,2]
   The output is saying column 1 has a minimum needed width of 2
   The largest object in the 3rd column is 3 wide, so the minimum for that column is 3
   This means smaller pieces in that column need padding.
   (this is so that ".." will line up with "#u#". You just add a space ".. " taa daa lol)
  
   Phew! That wasn't so hard was it?
   Now we have to delve into the nasty code lol.
   This is where it gets a bit trickier, but with the above concepts in mind,
   it shouldn't be that bad ;)
  
   So here is the blunt explanation first, and then I'll break it down.
  
   Alright, so the basic structure of "rows" ("exampleData" in my example)
   is
     [ row1, row2, row3, row4, row5]
   and the structure of any row is
     [ itemFromColumn1, itemFromColumn2, itemFromColumn3, itemFromColumn5, itemFromColumn5]
   Let's represent the first row as ordered pairs, where we have
   TextCell(m,n) is the TextCell of row N(y) at position M(x)
   This just makes sense though, doesn't it? rows are the y values, columns the X values
  
   If you think about it like a grid then we have each row is
     //rowN, where n is the row number 1, 2, 3, 4, or 5 etc
     [ TextCell(1,n), TextCell(2,n), TextCell(3,n), TextCell(4,n), TextCell(5,n)]
   Thus the whole array is really like the following diagram, which is basically a grid
     [ TextCell(1,1), TextCell(2,1), TextCell(3,1), TextCell(4,1), TextCell(5,1)]//row1
     [ TextCell(1,2), TextCell(2,2), TextCell(3,2), TextCell(4,2), TextCell(5,2)]//row2
     [ TextCell(1,3), TextCell(2,3), TextCell(3,3), TextCell(4,3), TextCell(5,3)]//row3
     [ TextCell(1,4), TextCell(2,4), TextCell(3,4), TextCell(4,4), TextCell(5,4)]//row4
     [ TextCell(1,5), TextCell(2,5), TextCell(3,5), TextCell(4,5), TextCell(5,5)]//row5

   In my model I start the numbers at 1, but they really start at 0 because arrays
   start at 0.
   But as you should be able to tell, the row number is clearly the "Y" value in the grid
   And the index into any given "row" is like the "X" value into the grid.
  
   Now how does this apply to understanding the code?
   Well, the code returns just the first array of the above:
     [ TextCell(1,1), TextCell(1,2), TextCell(1,3), TextCell(1,4), TextCell(1,5)]//row1
   mapping each slot to a reduction of all the rows containing elements of that column.
  
   First, let's understand the outer code, to understand what role 'i' has in all this,
   but then let's dive straight into the inner code first, so we can understand the outer
   code in relation to it.
  
   Alright, so we first have
     return rows[0].map(function(_,i){ //inner code blah blah});
  
   The map() function takes two parameters (or more, but don't worry about that)
   They are as follows
     map(element, index_into_array)
   We aren't using the element itself, because we are doing some super confusing
   sneaky stuff and don't need it.
   (basically if we just have map(element) it takes each element in the array and uses it
    to determine what to map that slot to.
    We are just using the index into the array to figure out what to map the slot to
    This means we are just using the X values, or column numbers, to determine
    what to map each slot to.
    Each slot represents a column, so slot 0 represents column 0(the first one, col 1)
    And we are only using that information, not the 'row' element stored in that slot,
    to figure out what to put in that slot.
    This is a highly unusual way to use map, (based on the prior examples) but it is nifty.
    (tho confusing as all hell)
    )
   All we need is the index into the array itself.

   This is equivalent to the column number, since the index into rows[0]  
   is the index into
     [ TextCell(1,1), TextCell(1,2), TextCell(1,3), TextCell(1,4), TextCell(1,5)]//row1
   In our model that would seem to be 1, 2, 3, 4, 5, the x values, but it is really 0 - 4, since
   arrays start at 0. This is clearly the X value of our grid, or column number.
  
   Okay, so i represents the column number, or 'x'.
   It would have been better if the Eloquent code had named it as such, but sadly it
   didn't.
  
   Now that we know i represents the column number, let's dive into the inner code.
    return rows.reduce(function(max, row) { //blah blah}, 0);
   Notice that second parameter again? The zero?
   That means the first time through the reduce's 'max' is 0 and 'row' is rows[0]
   (the variables 'max' and 'row' take on those values the first time reduce does its thing)
   This is the same idea as what we saw with rowHeights() earlier.
  
   We are reducing all of the rows based on max, and the individual row.
   Let's look at the inner code to figure out what is going on.
     return Math.max(max, row[i].minWidth());    
   Woah! There is the 'i' again! Wait, what is i really?
     return Math.max(max, row[columnNumber].minWidth());
   Oh! okay.. sooo.. this is saying.. what exactly?
  
   You have to remember that this reduction is embedded inside of a map.
   This means that 'reduction', reduce(), is called 5 times, one for each time map maps an element
   of row[0]. (row[0][0] - row[0][4]
   This means each time reduce() is called 'i', columnNumber, is fixed, constant.
   Thus, reduce compares each _>rows<_ against="" another.="" br="" column="" element="" i="" one="" th="">   (i.e. it compares each X slot of the grid with the ones right below it, incrementing the Y value)
     
   Basically, in other words, putting all the pieces together, we get:
    
     function colWidths(rows) {
      //rows[0] = [ TextCell(1,1), TextCell(1,2), TextCell(1,3), TextCell(1,4), TextCell(1,5)]
        return rows[0].map(function(_, column) { //column is columnNumber or the x value of the grid
         
          return rows.reduce(function(max, row) {
         
            return Math.max(max, row[column].minWidth());//using the X value as the fixed
                                                         // Y value
            /*
              i.e. for each row compare row[column] against the prior row's row[column]
              i.e.
             
              1st time map does what it does
              map(row[0][0]), column = 0, to the result of reduce()
                reduce() max = 0, row = rows[0]  //[y][x(column)]                       (x,y)
                  return Math.max(          0, rows[0][0].minWidth()); //Max(0, TextCell(0,1)) 
                  return Math.max(priorResult, rows[1][0].minWidth()); //Max(0, TextCell(0,2))
                  return Math.max(priorResult, rows[2][0].minWidth()); //Max(0, TextCell(0,3))
                  return Math.max(priorResult, rows[3][0].minWidth()); //Max(0, TextCell(0,4))
                  return Math.max(priorResult, rows[4][0].minWidth()); //Max(0, TextCell(0,5))
               //result[0] is now full, and contains the min
             
              2cnd time map does what it does
              map(row[0][1]), column = 1, to the result of reduce()
                reduce() max = 0, row = rows[0]  //[y][x]  //comparing to model start @ 1
                  return Math.max(          0, rows[0][1].minWidth()); //Max(0, TextCell(1,1))  
                  return Math.max(priorResult, rows[1][1].minWidth()); //Max(0, TextCell(1,2))
                  return Math.max(priorResult, rows[2][1].minWidth()); //Max(0, TextCell(1,3))
                  return Math.max(priorResult, rows[3][1].minWidth()); //Max(0, TextCell(1,4))
                  return Math.max(priorResult, rows[4][1].minWidth()); //Max(0, TextCell(1,5))
               //result[1] is now full, and contains the min
             
              3rd time map does what it does
              map(row[0][2]), column = 2, to the result of reduce()
                reduce() max = 0, row = rows[0]  //[y][x]  //comparing to model start @ 1
                  return Math.max(          0, rows[0][2].minWidth()); //Max(0, TextCell(3,1))  
                  return Math.max(priorResult, rows[1][2].minWidth()); //Max(0, TextCell(3,2))
                  return Math.max(priorResult, rows[2][2].minWidth()); //Max(0, TextCell(3,3))
                  return Math.max(priorResult, rows[3][2].minWidth()); //Max(0, TextCell(3,4))
                  return Math.max(priorResult, rows[4][2].minWidth()); //Max(0, TextCell(3,5))
               //result[2] is now full, and contains the min

              4th time map does what it does
              map(row[0][3]), column = 3, to the result of reduce()
              //once again, let me reiterate, 3 is the X value, but due to the way 'rows' is set up
              //compared to the grid, x and y are swapped
              //rows[y][x] is the TextCell at point (x,y)
                reduce() max = 0, row = rows[0]  //[y][x]  //comparing to model start @ 1
                  return Math.max(          0, rows[0][3].minWidth()); //Max(0, TextCell(4,1))  
                  return Math.max(priorResult, rows[1][3].minWidth()); //Max(0, TextCell(4,2))
                  return Math.max(priorResult, rows[2][3].minWidth()); //Max(0, TextCell(4,3))
                  return Math.max(priorResult, rows[3][3].minWidth()); //Max(0, TextCell(4,4))
                  return Math.max(priorResult, rows[4][3].minWidth()); //Max(0, TextCell(4,5))
               //result[3] is now full, and contains the min
             
              5th and last time map does what it does
              map(row[0][4]), column = 4, to the result of reduce()
                reduce() max = 0, row = rows[0]  //[y][x]  //comparing to model start @ 1
                  return Math.max(          0, rows[0][4].minWidth()); //Max(0, TextCell(5,1))  
                  return Math.max(priorResult, rows[1][4].minWidth()); //Max(0, TextCell(5,2))
                  return Math.max(priorResult, rows[2][4].minWidth()); //Max(0, TextCell(5,3))
                  return Math.max(priorResult, rows[3][4].minWidth()); //Max(0, TextCell(5,4))
                  return Math.max(priorResult, rows[4][4].minWidth()); //Max(0, TextCell(5,5))
               //result[3] is now full, and contains the min
            */
         
          }, 0);
       
        });
     
      }  
   So basically, this uses the first row as an anchor, and reduces each column based on
   using the index into that row (i) as a fixed index into each row.
   i.e.
   row[0] is mapped using 0-4 as keys
   0: is mapped to a reduction of rows[all][0] based on which has the maximum minwidth
   1: is mapped to a reduction of rows[all][1] based on max minwidth
   2: mapped to reduction of rows[all][2]
   etc
  
   The whole "reduce" thing is like basically doing this
       var result = [];
      
       //this part is analogous to the outer Map loop
       //X is equal to column number, etc
       for(var x = 0; x < rows[0].length; x++){
         result[x] = 0; //the default for Max as the second parameter to reduce()
        
         //This part is analogous to the inner reduce loop
         //Stay at a fixed X value and loop through each item in that column
         //until you find the largest minimum width needed to draw that column
         for(var y = 0; y < rows.length; y++ ){
           if(rows[y][x].minWidth() > result[x]) //get the maximum minWidth
             result[x] = rows[y][x].minWidth();
         }
       }
  
   I hope this all makes sense?
   It was kinda harder to explain than I had imagined, but hopefully it made sense.
   I was a bit rambly, but if you look at and read everything I wrote
   things should eventually click.
   :)
  
  

*/
function colWidths(rows) {
  return rows[0].map(function(_, i) {
    return rows.reduce(function(max, row) {
      return Math.max(max, row[i].minWidth());
    }, 0);
  });
}

Sunday, August 30, 2015

Eloquent Javascript Chapter 6

Hello people! :) *cheesy smile*

Today I was working through Eloquent Javascript, which you can read for free and work through for free online here http://eloquentjavascript.net, which is a super awesome book teaching programming concepts and Javascript. 

It can get pretty damn confusing tho, although I was breezing through it until I hit Chapter 6.
I am going to write a post tomorrow or later tonight(not likely) explaining everything so anyone can understand it.
It was sooo randomly difficult and unexplained that it really pissed me off.
I can understand it, but it is unnecessary to make it so.. non-intuitively presented.
It is much harder to look at someone else's code in little isolated bits without any context and without any of the knowledge that went into the brainstorming behind the code being looked at.

Yup, case-in-point, here is an excerpt from my notes as I was trying to figure everything out:

  "/* OKAY
     so this is GOD AWFULLY CONFUSING AS SHIT
     But this is what it means:
     It maps each slot in the 0th index of the rows array to the minWidth of all the columns of that index [...]"

I don't want to ^give the whole quote out of context, plus I just wanted to show just how frustrating it was lol. I mean look at that colorful language xD

I am going to be breaking Chapter 6 down into bite-sized manageable bits so anyone can understand it.
There was one particular thing that was bothering me, which I finally figured out.
I will go over that too, but I'll mention it now in case it is throwing anyone else for a loop. (no pun intended LOL)


So we have the following code written by the author(with the example Rows object for context):

/*
0:    [
0:    TextCell{text: ["##"]}
1:    TextCell{text: ["  "]}
2:    TextCell{text: ["##"]}
3:    TextCell{text: ["  "]}
4:    TextCell{text: ["##"]}
]
1:    [
0:    TextCell{text: ["  "]}
1:    TextCell{text: ["##"]}
2:    TextCell{text: ["  "]}
3:    TextCell{text: ["##"]}
4:    TextCell{text: ["  "]}
]
2:    [
0:    TextCell{text: ["##"]}
1:    TextCell{text: ["  "]}
2:    TextCell{text: ["##"]}
3:    TextCell{text: ["  "]}
4:    TextCell{text: ["##"]}
]
3:    [
0:    TextCell{text: ["  "]}
1:    TextCell{text: ["##"]}
2:    TextCell{text: ["  "]}
3:    TextCell{text: ["##"]}
4:    TextCell{text: ["  "]}
] */

function rowHeights(rows) {
  return rows.map(function(row) {
    return row.reduce(function(max, cell) {
      return Math.max(max, cell.minHeight());
    }, 0);
  });
}

function colWidths(rows) {
 return rows[0].map(function(_, i) { //rowZero.map( function(element, index) {
   
    return rows.reduce(function(max, row) { //reduce each row into a minWidth for that row
      return Math.max(max, row[i].minWidth());
    }, 0);
  });
}


So, if you look, you'll see (inside function rowHeight)
row.reduce(function(max,row){
   return Math.max(max, cell.minHeight());
}, 0)

Now, if you are me, you think.. okay, "row" contains "cell"s, so it contains TextCell objects.
and "reduce" takes the first object, compares it to the second, and returns whatever it feels like, replacing them both with something else, until there is only 1 survivor left.

Thus, when I saw Math.max(max, cell.minHeight())
I assumed max would be an object of type TextCell, and that cell.minHeight() would, of course, resolve into a number (integer).
But if max is an object, then Math.max should fail miserably and return NaN.
So why does it work?!

When I finally figured it out, it made so much sense.
The trick is the second parameter to reduce, which is an argument you can use as the first argument to compare against the arrays contents, instead of using the array's contents as the starting point.

So , when we say
row.reduce(function(max, current){}, 0)
This means that 0 will be put in first for max, and current will be the 1st object in the array
Thus, Math.max(max, current.minHeight()); will never be NaN
because the first time it is Math.max(0, current.minHeight());
then every time after it becomes
Math.max(oldResult(which is a number), current.minHeight()(which is the next thing in the array));

I hope this (awfully formatted) quick post helps someone.
If you have any questions, don't hesitate to reach out. :)

~James

Sunday, May 3, 2015

Noktaj Notoj

Saluton karaj legantoj! :)

Cxi tiu skribajxo estas pri mia jxus-kompletita legado, pri Scienco kaj la Matematikoj. (Mi studas la matematikojn kaj komputalajn sciencojn, do mi vere gxuas tiujn studobjektojn/studinteresojn)

(se vi trovas iujn erarojn en cxi tiu pagxo, bonvolu komenti :) Dankon!)

Mi estas leginta la libro nomata "La Vojo al Realeco" (Eble tradukita malbone, mi ne uzas Esperanton antaux longe, mi paronpetas), verkita de Roger Penrose.
La libro estas tre tre granda kaj dika, kaj profunde interesa.
Mi volas legi gxin pli, sed gxi estas tre malfrua nun, kaj mi havas tro multe da interesojn mi volas ankaux studi.
(Kiel la matematikojn, kaj multajn lingvojn, ktp ;P)

Gxi sentas bone uzi kaj skribi Esperanton denove, sed mi probable forgesis kelkajn vortojn aux pli..
Kiel mia studado de la japana, gxi estas tro facila forgesi vortojn se vi ne uzas ilin.
Sed, la japana estas mojose bela kaj interesa, do mi certe studos gxin plu. ;)
Mi volas ankaux studi la hispanan, kaj cxinan, kaj francan, ktp, sed mi ne havas multe da tempon pro miaj planoj pri religiaj aferoj (mi ne scias la vorto por la afero, sed... "Kiam oni volas, senpage kaj volante, instrui religiajxojn kaj servi iu Pregxejo plimembrigxi.

En la angla mi iras/ decidis iri en(al? je?) "Mission".
Dum du jaroj mi instruos kaj helpos la pregxejo gajni pli da membrojn, kaj mi helpas personojn trovi kontecon kaj felicxecon.
La religio mi estas parto estas tre familio-pri-ante, nu...
familio-koncernante, pensas kaj tre amas la familiajn strukturojn kaj idealecon, kaj laboras ege kontentigi familiojn.

O! Mi gxis nun ne menciis iom pri mia legado!
Nun mi ekas :)

La libro diris pri la "Ideala Mondo kie la Matematikaj Ideoj kaj Ajxoj Vivas".
(Cxi tiu estas profunda ideo, kaj mi nur legis la 32 pagxojn de la unua cxapitro (<- eble hispana vorto E-igxigita, mi ne certas @_@ Mi korektos pli malfrue) )
Gxi estas tre interesa kaj, kiel mi skribis supe, profunda.
Mi pensemas ke realeco estas tre kompleksa kaj interesa, sed ankaux tre bela kaj malordinara.(nu... "unique" angle. interese, sed malhelpante, mia menso volas uzi kaj pensi japanajn vortojn xD)

Oni ne kutime pensas pri la ideo ke matematikaj ideoj havas ilian proprajn vivojn kaj esteco kiel ajxoj ne de nia mondo, sed vivante en ilia propra mondo.
Mondo de idealeco kaj (abstraktaj?) ideoj.
Gxi gravas cxu la vereco de iu matematikajxo (plue skribata "matemajxo") ekzistas sendependante je nia realeco.
Ke matematikaj ideoj kaj verajxoj ekzistas cxu ni trovas ilin aux ne.
Ke granda trovaro ekzistas ke ni ne ecx komprenas.

Tiu estas ege profunda ideo, kaj, laux mi, estas tre grava.
(sed, vere, mi estas Matematikisto. Sed la matematikoj estas parto de cxiuj, kaj ilia graveco estas bone konata/sciata.)

La matematikoj estas tre bona modelo de nia mondo, tre tre precisa modelo.
Ege precisa.
Tiu estas stranga, cxu ne?
Gxi estas strange kaj profunde precisa.

Mi volas tuj legi la tutan libron pro mia interesado, sed triste la libro estas 1000+ pagxoj kaj dikas kun matematikojn me ne jam studis.
("dikas kun" => estas dika koncernante matematikojn me ne jam studas kiuj cxiuj estas malfacile kompreneblaj (sed mi probable povas, sed ne certas))

Nu... mi dormemas, kaj volas studi aliajn ajxojn antaux tiu dormado.
Do, mi "Bonan Nokton"as vin, kaj esperas ke vi havas bonegan fojon kaj trovas felicxecon en cxiu afero de via vivo. :)

Sincere via,

~James D.