Posts for Bobo_the_King

Experienced Forum User, Published Author, Player (79)
Joined: 8/5/2007
Posts: 865
That's a very thoughtful comment, p4wn3r, and I hope you copy and paste it to other forums so it reaches a wider audience. I've long had a sort of vague aversion to programming-- there's a whole lot of stuff I don't get (currently struggling with closures) while a lot of the stuff I do get sits uneasily in my brain. As an analogy, I hated writing reports in school and since graduating, I've had many opportunities to read students' reports, provide feedback, and even produce some of my own. I've grown to understand that while I was pretty bad at writing reports in college, I've become pretty good at it since then. (After all, these latest posts of mine are nothing but informal reports.) But assign that to me as a task or make it my career path? Blech, please no. That's much how I feel about programming and I think just about anyone reading this can relate somehow; we've all got subjects that give us less satisfaction despite being at least okay at them. Regarding OOP specifically, I think one reason I've never much liked it is because I've simply managed to avoid any tasks for which it would be a good paradigm. Two places I've seen it used (at least potentially) are in GUIs and video games. When I now look at my possibly favorite game, Mario 3, I can easily imagine each enemy as an object, assigned aspects like type, position, and behavior. You'd almost be a fool to avoid OOP when making a video game, or at least one in the vein of Mario 3. Another issue is that when I was forced to learn Java one semester back in college, I had a very poor understanding of hardware architecture and what goes on behind the scenes. I obviously knew about hard disk space from a practical standpoint and had some notion of using magnets to flip bits, but how hard disks differed from RAM, especially in their access times, was pretty foreign to me. Gaps in my knowledge such as that made it such that when I was programming in Matlab a few years later, I didn't understand why my programs would run so slowly when I had arrays growing dynamically as space was needed. The preallocation of memory that we were forced to do under Java always elicited a "huh?" from me and I now see that having your data structures grow without strict bound puts a lot of pressure on cleanup routines that have to copy and shove nearby data out of the way to make room. It was only when I started learning assembly for TASing that I began to make these important connections: computers are a form of Turing machine, allocating memory is crucial, and object-oriented programming has an important place in the way we code. Now whenever I'm coding or struggling with a new concept, I always have an eye toward what the corresponding assembly language might look like, at least conceptually. I think I've made it clear, but just to reiterate, none of that means I'm good at any of the above, just that I think I can connect the dots in the big picture in a way that ten years ago, I'd have said it's all completely dumb and arbitrary. Even though a handful of people in my life have suggested, "Why don't you get into programming as a career path?" I've always been resistant to the idea. Your list of questions bolsters my stance, as none of them screams to me, "Ah yes, that'd be the life for me!" On a highly tangential note, I sometimes think back to a community college job I once applied to and the professor I was to work for wanted me to write a short Word document. I did one or two basic formatting changes-- I think I centered the text-- and he remarked, "Wow, you're much better at this than I am!" (I somehow didn't get the job, despite Professor Dinosaur not being able to use a word processor.) That's what I think of when I imagine programming as a career: your boss has no idea what you're doing so he throws a pittance in your direction so you can do a bunch of basic stuff. There are "sexy" programming jobs out there, but they're highly competitive and I already pretty well know I can't function at that level and deal with criticism and demands from my bosses and/or colleagues. Instead, I'd be left with the gruntwork. Programming is really a weird career path where there's this huge disparity of need between, as you point out, companies that just need basic tasks done because everyone there is tech-illiterate versus domains where coding fast, elegantly, concisely, efficiently, or creatively actually gets you a six figure salary and some prestige. On the whole, it strikes me as a profession where being positively elite and having "the mind of a programmer" will get you everything you want, but for people who get roped into it because they hear people chanting "STEM" but otherwise show no great aptitude for it, programming will earn you a living, just not a particularly good one. By the way, I have an upcoming project for which OOP is definitely a good paradigm choice and I'm hoping I can scrape something together without falling flat on my face.
Experienced Forum User, Published Author, Player (79)
Joined: 8/5/2007
Posts: 865
Quick update: I felt a little guilty about posting the critical temperature image in my previous post since I had to follow it with, "If you look closely, you'll see that it's a bit 'clumpier' than the T=3 image." It was kind of disappointing to me because it didn't really exhibit the structure at all scales I'd hoped to show. Yet I pretty much knew it was correct because the program is pretty simple and it definitely worked in temperature domains above and below the critical temperature so I just rolled with it. Well, there's a reason the image was disappointing. Here's what Wikipedia has to say:
Wikipedia wrote:
It is important to note that the Metropolis–Hastings algorithm does not perform well around the critical point due to critical slowing down. Other techniques such as multigrid methods, Niedermayer's algorithm, Swendsen–Wang algorithm, or the Wolff algorithm are required in order to resolve the model near the critical point; a requirement for determining the critical exponents of the system.
So the issue was that I had started from a random state and thanks to the underlying mathematics, it was converging to the "structure at all scales" state very slowly. I'm not familiar with Niedermayer's, Swendsen-Wang, or Wolff algorithms, nor do I want to double the size of my program or worse by attempting to implement them. Instead, my workaround was to adjust the temperature. Through a handful of tests at various temperatures, I was able to determine a "settling time" of about 500 frames over which clusters coalesce when the temperature is below the critical temperature and clusters break apart when the temperature is above the critical temperature. I therefore set the temperature to oscillate every 500 frames, decreasing the magnitude of its oscillations by 0.8 each time. The final temperature is still the critical temperature, 2.2692, it just approaches it asymptotically. Here's what it looks like after having run for about 20,000 frames, about 40 cycles: The temperature agrees with the critical temperature to the fourth decimal place. I hope you now believe in structure at all scales. Here's the updated code.
Experienced Forum User, Published Author, Player (79)
Joined: 8/5/2007
Posts: 865
Get the code here! The Ising Model of a Ferromagnet A two-part adventure... I've now completed half of a long-term dream of mine: implementing the Ising model of a ferromagnet. This is a really cool physics exercise that attempts to explain (at least qualitatively) why iron can be magnetized but beyond a certain critical temperature (the Curie temperature), that magnetization disappears. We imagine a chunk of iron as flattened out in two dimensions on a grid, made up of individual iron atoms. The magnetization of each of these atoms (spin-up or spin-down, we call them) is influenced by its nearest neighbors. If its neighbors are all spin up, it will tend to be spin up as well and likewise vice versa. If this were all there were to ferromagnetization, the picture would be very boring: single atoms flip until three of their neighbors are alike, then they remain stuck in that position. The extra wrinkle comes from randomization, which in the realm of physics is manifested through temperature. Give the material a nonzero temperature and there is a nonzero probability that each dipole will flip despite it being energetically unfavorable to do so. This probability of spontaneously flipping is e^(-U/kT), where U is the difference in energy between flipping and not flipping, T is the temperature, and k is Boltzmann's constant (e is, of course, 2.71828...). The justification for this comes from Boltzmann statistics and something called the Metropolis algorithm but if you're looking for a detailed explanation here, you won't get it from me because it's been a long time since I studied this stuff, I wasn't very good at it in the first place, and I don't want this post to ramble on and on and on... as I've been known to do. But knowing physics isn't even necessary to translate the pseudocode into Lua! This is a standard simulation and Thermal Physics by Schroeder is able to knock out the pseudocode in about a page, maybe 40 lines or so. I've tried to gussy it up a bit for Lua's quirks and my own version is about 100 lines. I can't say I've learned much from this project, but one thing that came as a surprise is that using floor(2*math.random() - 1) to set my initial state caused everything to go bonkers and I ended up with absurd results: an initial state that was graphically random yet showed a strong net magnetization numerically, which then migrated to a state that was dominated by the spin-up state yet showed no net magnetization numerically. I still have no idea what was causing that. Just use 2*math.random(2) - 3 instead. All right, if you're skipping all my paragraphs (and I don't blame you if you are), you should know that this project produces pretty pictures (well, "pretty" by a fairly low standard). Let's start with the most boring, in which I set the temperature to 3: White represents spin-up, black represents spin-down. If the temperature were high enough, the pixels would be completely random and although there doesn't seem to be much order in the above image, if you look closely you'll find that there's a little bit of "clumping" and pixels have some inclination toward coalescing in small clusters. We get more interesting domains when we set the temperature to something like 1.5 and run it for a couple minutes: Well now I'm sure you believe me when I say that pixels are likely to coalesce in clusters. Any small clusters get "eaten away" and erode to zero pixels rather quickly. This also smooths out the boundaries of the large clusters that we see for much the same reason-- any sharp protrusions represent pixels that are more likely to be surrounded by three pixels of the opposite color, causing them to flip. (On a tangential note, the pattern produced resembles a Turing pattern and I'm sure someone has made the connection between the two, showing that at low temperatures, the Ising model produces some manifestation of Turing patterns. There's also a great tutorial on how to produce Turing patterns in PhotoShop in a few minutes, although I much prefer the free online alternative, Photopea.) We've shown in this crude model that this material can be "magnetized". That is, once the spins are preferentially aligned in one direction (say, by imposing an external magnetic field), they remain aligned and will persist. You can then carry this magnet around and observe its net magnetization by sticking it to a refrigerator or something. But to be clear, this is apparent in the above picture because it permits large structures-- structures that span the entire image. You can easily navigate a path that runs from one side of the image to the other while staying entirely within the black domain. So I've shown you one image corresponding to a "high" temperature that has tiny clusters and a second image corresponding to a "low" temperature with large clusters. The interesting thing-- to me at least-- happens when we strike a balance between the two. Can we find a "critical temperature" that exhibits structure at all scales? Yes, here it is at 2.2692: Edit: The above image isn't wrong by any means-- it is at the critical temperature and I ran it for a good long while. But it turns out that the system equilibrates very slowly when near the critical temperature. I've gotten around this issue. See my following post. This may not seem like much at first, but if you look closely, you'll see that it's a bit "clumpier" than the T=3 image and there are in fact clusters that are large as well as small. (I'm not quite sure how to quantify this, but I've long imagined to do so we'd pick a pixel at random and it would be just as likely to be part of a tiny one-pixel "clump" as it is to be part of a massive grid-spanning clump or anywhere in between.) This structure at all scales gives rise to some interesting predictions. I once saw a seminar in which this phenomenon was demonstrated by allowing material to precipitate out of a solution, turning a cloudy white in an instant, the color being a product of the Rayleigh scattering of light of all frequencies by particulates of all sizes. This was then used as a metaphor for precipitation events in the stock market (no, I'm not kidding). And it is this same structure at all scales that will motivate (I hope) part 2 of my little project, a second, unrelated piece that I'm actually most interested in. Stay tuned...
Post subject: Bobo's continuing adventures in Lua
Experienced Forum User, Published Author, Player (79)
Joined: 8/5/2007
Posts: 865
Get the code here! Preamble (Yeah, you can skip this if you want.) After returning to the site about two weeks ago, I was freshly inspired to take up programming again, having laid off it for several years. It's been very refreshing to scratch that itch again. Contrary to my reputation 'round these parts (to the extent I think I have a reputation), I don't consider myself a good programmer at all. I am, rather, a determined programmer with a very limited set of tools, although I hear in some circles that that's really all you need to be a good programmer. But I stand by my self-assessment. I don't even "get" object-oriented programming and every foray of mine into it has left me not only confused but outright contemptuous toward programming as a profession. "This makes no sense! This whole paradigm has to be a fiction!" (I've grown a little and am beginning to sort of understand object-oriented programming at a conceptual level, but I wouldn't dare say anything I've ever programmed has been object-oriented in any meaningful sense. Even if/when I figure it out, I'll probably always think of programs as code that, you know, does stuff, not objects. I'm a verb guy, not a noun guy.) Anyway, I've found this popular guide that had somehow slipped past me all these years and I've been following along with it and diligently taking notes. One thing that I've learned that I don't think I had a good grasp of when I last used Lua is that it uses associative arrays, which are mathematically like directed graphs (admitting loops, as well). It became clear to me why Lua's tables were always lauded as so versatile: an associative array is a generalized form of just about every data structure. Lists, linked lists, arrays, trees-- almost anything can be represented as an associative array. (Or maybe truly anything. I'm aware of more complex data structures, although they might be jury-rigged from associative arrays. In any case, they strike me as memory and/or computationally impractical.) You'll find just about all of the data structures I mentioned and more in my project below. The End So that's my life's story. I had this really versatile data structure to work with and immediately thought, "Well, what are associative arrays good for modeling? Markov chains!" When you type a word into your phone, it uses predictive algorithms based on the frequency of your previous texts to determine the most likely words you'll type next and offer them to you. I thought, "Why not do the same thing for English?" We can take collections of letters and string them together in a way that makes fake words! If my theory was right, these words would look like almost English, something that if you found it in the dictionary, you wouldn't be surprised to find there because it was just a little too obscure for you to know about it. That is why this post starts at "the end", because everything I built toward was based on constructing this Markov chain and I don't want you to leave because you're getting bored. I've represented the Markov chain pictorially below: Red circles encompass our syllables. (Throughout this post, I'll be using the word "syllables" very loosely-- it's any collection of characters, including single characters, characters with/without vowels, apostrophes, or starts/ends to words.) We start on the left, in the empty string "", then traverse the tree randomly until we land on a suffix, any string ending in _ (underscore). For illustrative purposes, I've decided to show two real English words. Follow the blue path and you'll read "_stochastic_" while the purple path leads you down "_pastiche_". Numbers in blue or purple are the weights of their associated arcs, which are proportional to the probability of traversing that arc (note the a --> st arc in both blue and purple agree that the weight is 42). For example, if the only arcs exiting "" are _s and _p with weights 89 and 77 respectively, there is a 89/(89+77) = 53.6% chance of following the "" --> _s arc and a 46.4% chance of following the "" --> _p arc. Thin lines in green represent arcs between nodes that are not taken in this random walk, but are still represented in the graph. Starts and ends of words are both represented by underscores. (So to be perfectly clear, this figure is a simplified version of what I produced. Differences include: 1) Every solitary character is represented somewhere in the full graph because no syllable pattern is perfectly consistent, 2) the syllables represented here need not correspond to syllables actually used, 3) loops are permitted (so if "ba" and "na" are syllables, ba --> na --> na is permitted), 4) arcs are permitted to go in either direction between two nodes, albeit with distinct weights (so both er --> go and go --> er are allowed with different probabilities), and 5) we traverse the graph randomly according to the weights and it is relatively unlikely that we will produce real words such as "stochastic" or "pastiche".) (Also, a quick look at Wikipedia says this might better be called a "flow network" or "flow graph". I'm not really up on the vocabulary-- ask FractalFusion.) (And finally, you may be aware that associative arrays do not naturally describe weighted directed graphs, such as the one in my first figure. Under the hood, each outgoing branch leads effectively to a single linked-list element with the weight and the destination node.) So that's the end goal. Unfortunately, a question immediately arises... Whence Syllables? Sure, I could just use this concept with individual letters, or every pair of letters, or hand-picked syllables. (In fact, that's what my rough draft of this program did.) But we're programmers! We should be able to automate this stuff. Let me introduce you to Huffman coding. These are variable-length codes that store more frequently-used symbols in shorter code words. They are the most efficient substitution cipher that can be constructed from a given file. (Other compressions may be somewhat more efficient, but as far as I can tell, they use more complex algorithms that can't be reasonably decoded by hand. I'm trying to emulate an efficient human brain here and Huffman codes are the way to do it!) I'm not going to walk you through Huffman coding here. Instead, you can stare at this figure until it makes sense to you: It's actually pretty easy to understand and once you get it, it makes a lot of sense why it's constructed this way and how it works. Also, incidentally, my program doesn't actually create any Huffman codes, it only computes the length of the code words, what I call the "Huffman score" for each character. With 28 characters (26 letters plus apostrophe and space), the naive way of encoding things is with five bits per character. This wastes many bits on common letters like e and s, which appear very often, while wasting code words on rare letters like q and z. Feeding the entire dictionary into my Huffman coding algorithm with only our solitary characters assigns three bits to code words for common characters e and _ (over 170,000 instances) while rarely used characters q and j (2,500 instances) get ten bit code words. This alone compresses the dictionary by about 10 percent! Here's a flow chart for what I'm talking about: We start with our solitary character alphabet, search for those letters in the dictionary, record their weights (the number of times they appeared), and run that information through the Huffman coding algorithm. Syllables Have More Than One Character... Right. So let's again jump ahead a little bit and suppose we have a list of candidate syllables that we'd like to find the Huffman scores for. Follow along with this diagram, concentrating on going from left to right, ignoring the feedback loop for now: We start with a list of syllables, including a through z, apostrophe, _, and some others. In the figure I've used s_ and ed as examples (s_ mostly signifies plurals, words ending in s while ed could be found in words ending in ed or words with ed anywhere else in them, such as "editor" or "credit"). We search for their frequency in the dictionary and use those weights to find their Huffman scores, as we did with our individual characters. (Another side note: The dictionary/word list I linked above, which I used throughout this project doesn't include single-letter words like "a" or "I", nor does it include contractions. I manually entered "a" and "I" (to very little consequence) and I decided to not bother with contractions. My program is still ready to work with apostrophes all the same.) Ah, but there's a problem! If you've paid close attention, you'll notice that the inclusion of new syllables changes the weights of other syllables because, for example, more instances of s_ and ed mean fewer instances of s, _, e, and d. Basically, the Huffman scores depend on the weights, which in turn depend on the Huffman scores. My solution is to use the just-computed Huffman scores to feed that back into the sample text to obtain a better approximation of the weights. Of course, this doesn't necessarily mean our compression is yet optimal. I iterate through this loop until the number of bits used to encode the dictionary is more than the previous iteration, then step back to the previous iteration and assume this local minimum is near a global minimum for the list of syllables. (Practically speaking, my program is able to reach this point in about three to five iterations, so it's computationally very reasonable and quickly homes in on a steady state. You'll also see that the final iteration(s) tend to show modest gains, maybe in the hundreds to thousands of bits out of about 8 million.) Weights are approximated via a greedy algorithm, which employs whatever syllable has the most marginal benefit over the syllables we would use if that syllable weren't there. For example, if the characters "a", "t", "i", "o", and "n" have Huffman scores of 6, 6, 5, 5, and 7 and syllables "at" and "ion" have Huffman scores of 13 and 10 while "ation" has a Huffman score of 18, its savings are 5 because if it weren't in our syllable list, we'd use "at" and "ion" at a cost of 23, not "a", "t", "i", "o" and "n" at a cost of 29. In this example, other syllables present that would save more than 5 bits are prioritized over "ation". If you want a real-world example, "qu" has outstanding savings at 16 bits per instance because it has a Huffman score of 9 compared with q and u's Huffman scores of 17 and 8, respectively. This also is a great indication that my program is working-- we'd expect "qu" to have a high priority because the vast majority of q's are followed by u's. The greedy algorithm probably isn't ideal and I don't quite have the motivation to program an exhaustive algorithm as it is very likely NP-hard and I expect its savings to be only marginal. Oh yeah, and in case two syllables have the same savings, the tiebreaker is whichever has more characters, as it shortens the target word the most. You Still Haven't Said Where the Syllables Come From We're there! We start with a list of syllables already in our extended alphabet. Follow this flowchart: I assumed that the best candidate syllables are those that are comprised of the best syllables already in our list. Two "popular" syllables are appended end-to-end (in either order) and offered as a candidate. This candidate must first meet a few criteria: 1) it cannot have any interior spaces (this would span multiple words), 2) it cannot be flanked by two underscores (this would be a full word, which again, is not what I'm trying to produce, plus it would be lame for only securing one match at most), and 3) it cannot already be in our "graveyard", syllables that have already been shown to not have matches. In the flowchart above, "qu_hyp", "ing_qu", "ing_ing_", "ing__hyp", and "_hyp_hyp" would all fail for having interior underscores. With them, "_hyping_" would fail for having two exterior underscores. Only "ququ", "quing_", and "_hypqu" are potentially viable, provided they aren't in the graveyard (which they almost certainly are, given that they look almost nothing like real English). Those three criteria are easy to check, so once a syllable has passed them, I can scan the dictionary for it. If the syllable appears at least twice in the dictionary, we add it to our formal list of syllables. (Why twice? If the syllable appears just once, it can't possibly save any space because we need to use at least the same amount of information it saves encoding it in our extended dictionary. Interestingly, this means "zyzzyva" is potentially a viable syllable because "zyzzyvas" is also found in the dictionary and they've got some really expensive letters in them. So far, "zyzzyva" hasn't shown up in my searches, but maybe I should just program it in manually and see what happens...) If a syllable appears once or never, we add it to the graveyard as a quick reminder that we never need to search for it again. I arbitrarily decided to grow my list of syllables just 30 at a time under the assumption that growing it too aggressively is not only computationally expensive but also might lead to certain "instabilities" in the algorithms, causing it to under- or over- score some syllables. Also, I've done nothing to prune syllables that made the cut but haven't been useful because they have negative savings. I did briefly investigate it by assigning syllables random Huffman scores over 50 or so trials and found that out of about 1,200 syllables that made the cut, only about 100 ever show up in any resulting extended alphabet. I'm being very conservative, assuming that perhaps two syllables might be junk but their child might produce major savings. After adding enough syllables to my satisfaction, all that remained was producing the graph according to how often each syllable transitioned to each other. So... Can I Have a Recap? (Or TL;DR?) Sure:
  1. Start with the dictionary and our usual alphabet, plus apostrophe and _. Convert the text to lowercase and replace everything with underscores except letters and apostrophes.
  2. Search the dictionary for each letter, assigning a weight to the letter according to how many times it appeared in the dictionary.
  3. Use these letter frequencies to compute a Huffman score for each character.
  4. Merge any two popular characters into a syllable. If this syllable passes a few viability tests, not least of which is appearing at least twice somewhere in the dictionary, add it to our list of syllables. Create 30 (or however many) new syllables in this manner. To give them the best chance of success, make each new syllable cost just one bit.
  5. Using our now extended alphabet, encode the dictionary again and use the resulting weights to compute the Huffman scores. This first encoding of the dictionary is completely artificial since we arbitrarily assigned the new syllables a Huffman score of 1, which can't possibly be done. The output Huffman scores, however, are possible, albeit not ideal.
  6. Repeat step 5 until the number of bits needed to encode the dictionary is minimized.
  7. Return to step 4 and repeat from there, growing our list of syllables as much as desired. I ran my program on this loop for about six hours and got the dictionary down from 1065 KB to 892 KB. I think if I ran the code for much longer and made some improvements, I could get that down significantly lower, maybe in the ~800 KB range.
  8. Optionally, conduct a "losers' tournament", omitting all syllables with at least one bit of savings and force it to use syllables that have negative savings, then try to fold these syllables back into our list. I did this and found some interesting losing syllables, but if I remember correctly, re-merging them with our list didn't produce any savings. None of them stuck.
  9. Optionally, assign each syllable random Huffman scores and savings and see if we've accidentally excluded some good ones because they were never given a proper chance. I did this for ~50 iterations and found that over 90 percent of syllables are never used and will probably do just as much good in the graveyard. I put these syllables in a new table I called "hospice", but I haven't done anything else with them.
  10. Optionally, just add some syllables manually. I haven't done this, but I have been disappointed that "olog" hasn't made the cut, since it permits --> "ic", "ic" --> "al_", "y_", "ies_", "ist", "ist" --> "s_", "ism", "ism" --> "s_", "ize", and "ize" --> "s_", all off the top of my head. Instead, "ologi" is the form my program prefers, which admittedly is still pretty good. Anyway, the point is that brute calculation might not produce the best results, but I certainly can draw inspiration from syllables that have made the cut.
  11. Using our finished list of syllables, construct a weighted directed graph representing the likelihood of transitioning from each syllable to each syllable, if permitted.
  12. Randomly walk this graph according to the arc weights.
  13. Optionally, clean up the results by excluding a) words with no vowels (sorry "hmm", "shh", and "cwm"), b) words with letter triplicates (nooot alllowwwed), c) words already in the dictionary (because, you know, they're supposed to be fake words). I wrote this code but never actually incorporated it...
For Goodness' Sake, Bobo, Does it Work??? Hell yeah! I mean, I think there are probably a few errors in there, including a potential miscalculation of _ frequency, which I just thought of. But leading syllables (most savings per instance) include:
  • abilit (top saver, encoded in 10 bits and saving 18 bits)
  • nesses (but why not "nesses_"?)
  • qu
  • ously
  • ologi
  • ities_
  • comp
  • ing_
  • ation
  • ight
There are also some surprises soon after that, including _hyp, nde, cula, and vel. But the point is that these all look like English, so they're great building blocks. And what do these building blocks produce?
  • sapsuopperagentization
  • graphed
  • wols
  • claympherulations
  • precounhism
  • compens
  • animseltismicalcalvol
  • sestoushs
  • st
  • tymphaturate
  • kaziontration
  • troussed
  • asurgs
  • overterressign
  • distirdignallle
  • fingulticulas
  • coggamioncoded
  • toolatibilchernosittptindiness
  • devolideously
  • henlists
  • initalg
  • dists
  • fibrininesses
  • nated
  • slementarysting
  • ser
  • comftieingudredert
  • in
  • whectoman
  • fibrisequambativenesses
  • unbirringenufficadricalise
  • oilboateangeraugherack
  • isal
  • provengwintibal
  • nit
  • punatrever
  • ser
  • drinationisttlefonter
  • earities
  • targeourals
  • nah
  • drawfillogogea
  • regs
  • rastical
  • lan
  • jophalization
  • addishaporitides
  • poutheter
  • salize
  • grothinoituchygly
Prostetnic Vogon Jeltz, eat your heart out! Get the code here!
Experienced Forum User, Published Author, Player (79)
Joined: 8/5/2007
Posts: 865
Ferret Warlord wrote:
I'm not qualified to solve this problem, but I think you might be overthinking it. It may have more to do with the ratio between volume and surface area: by slicing off a chunk from a cube (supposing our ice block is a cube), you'll remove some ice, but you'll also remove some surface area, making it more difficult for heat to get in. You'd need to calculate a slice that would maximize both volume and surface area. I'll grant the puzzle as stated is a bit understated, failing to describe what the conditions are. Vague language like this leaves a lot open to interperetation.
No, I'm pretty sure I get the motivation of the problem. After all, for a given volume, the shape that (probably) melts the slowest is a sphere. (Rather a lot hangs on that "probably". I'd say something along the lines of the rate of melting being proportional to the curvature or something like that, but it's up to cleverer people than I to actually model that.) The problem is that this isn't "a given volume", we're lopping off some of it. My question is, is this ever worth it? I've given it a bit more thought and I think I'm homing pretty close to an answer. Let the cube of ice be given by volume U (that is, a set of points U, not the numerical volume). Let the smaller volume of ice be V, so V is a proper subset of U. We've lopped off U\V. Now I offer to reform block U by appending U\V back on to V to produce V∪(U\V), which is just U again. Allow these two blocks-- V and V∪(U\V)-- to melt for a short time. Any part of V away from where it was cut will melt no slower than U. (I'm unable to show this rigorously, but it seems intuitively true that insulating part of a block of ice should not make a different part melt faster.) Points on the interior of the surface adjoining V and U\V are insulated and will therefore not melt at all, whereas that same ice will melt somewhat in V. The only melting that we really need to consider is the ice at the perimeter of the surface of where V meets U\V. Here too, I imagine that the addition of U\V will only cause this ice to melt more slowly (though once again, I fall short of outright proving this). Thus, after this short time, encompassing block U melts to U' while smaller block V melts to V'. Based on my outline above, no part of U' has melted to within the interior of V'. The last step is to play this game again, now starting with U' and V'. By all the same arguments above, any parts of V' that melt are in the interior of U' and thus at all times, smaller block V lies entirely within larger block U, no matter how much time has elapsed, proving that a smaller block will always melt faster than a larger one that it can fit completely inside.
Experienced Forum User, Published Author, Player (79)
Joined: 8/5/2007
Posts: 865
This week's Riddler Classic has me puzzled. Not because it's especially difficult-- I have an answer I'm pretty confident in-- but the premise seems off to me. The premise: Make a block of ice melt more slowly by cutting off a piece of it. Intuition would point you in the direction that the best way to have your ice melt slowly is to have more ice. Intuition is often wrong, however. So can this be proven? One obvious issue is that we don't have a model for our melting ice. I could mumble a few words about the heat equation, but really the entire block could be at 0 degrees C while all the interesting physics happens at the boundary of the block as it melts. Then on top of that are the boundary conditions. I'd guess Dirichlet, but I'm vaguely aware that there are subtleties in heat transfer. Does our choice of boundary conditions even matter? Basically, given some model (which we'd have to decide on first), suppose we have two blocks of ice, one a proper subset of the other. Is it possible to prove that as they melt, the smaller block of ice remains a proper subset of the first at all times? The more I think about it, the more I imagine the answer is "yes", but I'm also excited by the idea of a counterexample. I haven't really put pen to paper in an attempt to solve it, largely because I don't have much confidence on the theoretical side of PDEs. One way I've looked at it is to consider the ratio of the heat flux to the block's volume. A second line of attack (which seems too good to be true, like it's almost a proof but might be either three lines or 50 pages away from a proper proof) is to just imagine that the smaller block is embedded in the first and point to its boundary where it lies within the larger block and say, "See? No heat entering here, so it melts strictly more slowly in the presence of the piece we lopped off." Any thoughts on this?
Experienced Forum User, Published Author, Player (79)
Joined: 8/5/2007
Posts: 865
Heyyyyy! I saw this in the Workbench and I felt bad that I could only view it as an outsider. Little did I know, if I'd checked the latest news on ousting a certain awful site admin, I'd be free to chime in. So I guess I just want to say great job, Darkman! Finishing this run had always been a pipe dream of mine and, to be honest, it still kind of is. Maybe someday we'll get our four mutant run with robust luck manipulation. But for now, congrats, Darkman!
Post subject: Hi, I'm new here.
Experienced Forum User, Published Author, Player (79)
Joined: 8/5/2007
Posts: 865
Hi.
Experienced Forum User, Published Author, Player (79)
Joined: 8/5/2007
Posts: 865
Samsara wrote:
Aardvark64 wrote:
I must say I find this character assassination a bit strange, unbecoming, and unprofessional.
Nach created, maintained, and vehemently defended a "parody" of WW2-era Nazi Germany. This page actively caused people to leave the site. If you want professionalism from TASvideos staff, then you should be happy Nach is no longer part of it.
Ha! I'm a little late getting the news but with this development, I'm back, baby! I guess I'd like to praise others' diplomacy in talking about Nach's history here, albeit not pulling punches with regards to how awful he's been for the site. I have a few choice words of my own, but I think using them would only reflect poorly on me, so just use your imagination. Good to be back in some capacity.
Experienced Forum User, Published Author, Player (79)
Joined: 8/5/2007
Posts: 865
Nach wrote:
Bobo the King wrote:
The only thing I'm sorry for is for slowing down the site and for perhaps people being offended without ever noticing that it was done in conjunction with a post condemning Nazism.
No. You don't apologize for how others feel. You apologize for your own actions. Period. "I'm sorry you..." is not an apology. It's become apparent to me that not only has Nach learned nothing from his "seventh reich" joke in extremely poor taste, he doesn't even acknowledge that he ever gave an apology. Nach has always been a controversial figure here, but I draw the line at spouting some nonsense about a seventh reich, being slow to deal with users with swastikas in their profiles, and as of today, issuing an un-pology. As long as Nach remains the site's chief administrator and refuses to so much as acknowledge that his joke was in extremely poor taste, I am done here. I had some interesting projects in my queue and have always enjoyed the community at large here, but I cannot condone Nach's policies and behavior. I am logging out as of submitting this post and will visit here much less frequently until Nach resigns or is removed from his post. I encourage others to join me.
Experienced Forum User, Published Author, Player (79)
Joined: 8/5/2007
Posts: 865
Nach wrote:
Bobo the King wrote:
Nach wrote:
It's disgusting to see people such as yourself labeling mocking Nazis as being Nazis.
Mel Brooks you are not.
I don't have to be, but I still find the characterization disgusting.
You apologized for that April Fools redesign and I am among those who felt that it was deserved and accepted your apology. Are you taking it back? Because I take your argument of, "Ugh! People can't take a joke!" to be tantamount to backtracking on your apology.
Experienced Forum User, Published Author, Player (79)
Joined: 8/5/2007
Posts: 865
Nach wrote:
It's disgusting to see people such as yourself labeling mocking Nazis as being Nazis.
Mel Brooks you are not.
Experienced Forum User, Published Author, Player (79)
Joined: 8/5/2007
Posts: 865
Warp wrote:
Could the hypothesis be generalized for all roots? In other words: The nth root of an integer is either an integer or an irrational number.
The method I outlined works irrespective of the order of the root. As with thatguy, I'll leave it as an exercise to you.
Experienced Forum User, Published Author, Player (79)
Joined: 8/5/2007
Posts: 865
One of my real analysis textbooks had an alternative proof that kind of resonated with me. Define x=sqrt(2). This is equivalent to the statement x^2 - 2 = 0. It can be shown (rational zeros theorem) that if there is a rational solution p/q to this polynomial, then p divides 2, q divides the coefficient of x^2, 1, and p and q share no common factors. The point is that our only options for p are +1 and +2 and our only choices for q are +1, giving us as our set of potential rational solutions -2, -1, 1, and 2. We plug each of these possibilities into the polynomial and see that none of them is equal to zero, proving that sqrt(2) is irrational. This is sort of overkill compared to Euclid's proof, but the upshot is that the theorem holds for any polynomial with integer coefficients. It allows us to prove the irrationality of complicated expressions, such as (2 + 5^(1/3))^(1/2) by...
  • Constructing a polynomial for which the number in question is a solution.
  • Applying the rational zeros theorem (which concerns only the highest and lowest order coefficients) to determine the set of possible solutions.
  • Testing all of these solutions within the polynomial. If none of them evaluate to zero, the number is not rational.
So for example, suppose we wish to prove the irrationality of sqrt(15). We write x=sqrt(15), and therefore demand that x^2 - 15 = 0. Our options for p are +1, +3, +5, and +15 while our options for q are just +1. None of 1, 3, 5, or 15 satisfy the polynomial, so sqrt(15) is irrational.
Experienced Forum User, Published Author, Player (79)
Joined: 8/5/2007
Posts: 865
Another week, another batch of riddles. The first one, involving the vitamins just took me a few minutes and I'm pretty confident in my answer. As you might expect, your chances of having your favorite flavor is pretty dang good. The problem involving the grasshopper is much harder and I've made very limited progress on it. I began by working on the more general case involving a lawn of arbitrary area. This allowed me to see that the optimal solution is not a circle, as was hinted. Suppose, for example, the area of the lawn were exactly pi*(15 cm)^2. Then we surely wouldn't want a circular lawn because any jump would necessarily take you out of the circle, since the radius of the grasshopper's jump exceeds the circle's diameter. I then speculated that the lawn might be a sort of narrow slit-- tapered at the ends, bulging slightly in the middle. Since that's a difficult shape to work with, I turned my efforts to finding the optimal dimensions of a rectangular lawn of infinitesimal area. This was much easier, requiring only a little calculus, but did require some attention as to whether the width of the rectangle is less than 2R (R being the radius of the grasshopper's jump) or greater than that amount, since these two cases break the rectangle up into regions where successful jumps by the grasshopper are given by 0, 1, or 2 arcs of its circle. Anyway, I'm not sure how clear any of that is, but I found that the optimal width of a rectangle of infinitesimal area is 3R. Incidentally, this lends a bit of credibility to my thin slit theory: if we were to add a small amount of area, it would likely be best to put it somewhere in the middle where the grasshopper has two ways to jump to this area and, should the grasshopper first fall in that new area, will have two exit points. So my next step will be to find the optimal dimensions of a cross-shaped lawn of infinitesimal area. That's about as far as I intend to go with the riddle this week unless I have some grand insights. It seems that it's a calculus of variations problem and a pretty pathological one at that. It probably would be best solved through programming. I can sort of picture a methodology in which individual pixels are included/excluded from the lawn based on maximizing how many other pixels it allows a jump from or to. I just don't care to program it myself. Edit: I've finished analyzing the cross-shaped lawn. Assuming the lawn remains divided into three regions each of width R (it gets tricky to analyze it otherwise), one half of its area is distributed at the thin ends and the other half is distributed in the fat middle. I'll leave the short step of determining its dimensions to anyone else. This suggests a starting point for the 1 m^2 lawn would be to assume it has two wings each of dimension 83.3 cm by 30 cm, plus a fat middle whose overall dimensions are 166.7 cm by 30 cm. This is almost assuredly less than ideal, since it rests on the assumption that the arcsine of x is approximately equal to x, which holds for sufficiently thin regions. If anyone is interested in continuing this analysis through some program, I'd draw up the region as a few thousand pixels, then move the pixel that contributes the least probability from its current spot to a spot that maximizes the gain in probability. By the way, it still seems to me that we're trying to maximize the number of pixels that are exactly 30 cm away from any pixel in question. For our cross-shaped region, I believe the optimal placement is somewhere not adjacent to the cross. This leads me to wonder if the lawn is necessarily contiguous and, if not, the solution might be some very unusual shape. Maybe it's a bullseye pattern? Hmmm... Edit 2: Well, I've done something wrong somewhere. I realized I never actually calculated the probability of the grasshopper landing in the lawn for either the rectangular lawn or the cross-shaped lawn. For the rectangular lawn, the probability was A/(3*pi*R^2). For the cross-shaped lawn, I found the probability to be A/(4*pi*R^2). This makes no sense because it indicates the probability decreases by including a fatter middle. I even confirmed that the derivative is strictly positive with respect to my one free parameter, consistent with an increasing probability. I'll need to check the consistency of my formulas.
Experienced Forum User, Published Author, Player (79)
Joined: 8/5/2007
Posts: 865
Billygod, since you seem to be receptive to criticism and understand the high standards we have here, I just want to say that you should redo this run properly with frame advance to make it perfect and then resubmit it. I think it's a good concept for a run and has a decent chance to be accepted. Don't be discouraged! (This is, of course, in contrast to the woefully imperfect runs of Super Mario Bros. we get about once a month these days. Those submitters should be discouraged, at least from trying to run Mario games.)
Experienced Forum User, Published Author, Player (79)
Joined: 8/5/2007
Posts: 865
Glad to hear I got it right. I think your logic is more clear as well. Here's the final image I produced, cleaned up a little bit so that the equidistributed colorings are all together on the left while failed colorings are on the right:
Experienced Forum User, Published Author, Player (79)
Joined: 8/5/2007
Posts: 865
I should be asleep because I have a long day ahead tomorrow. Instead, I've worked on this week's Riddler classic. I started by assuming, without loss of generality, that the tile with an area of 24 is red while the tile with an area of 21 is green. I then broke things up by determining the number of ways the remaining tiles could be added to the red or green groups to make them total 36. There were 17 ways to do so with the red group and 23 ways to do so with the green group. This would likely produce too many total to count. But some of those groups involve adjacent tiles of the same color. When applying this constraint, I find that there are 11 ways to distribute them in the red group and just 6 in the green group. This puts an upper bound of 66 different ways of distributing them (before considering the final two colors), which is still a bit large but seemed manageable by hand. I noticed that there are two different points on the left half where three different uncolored regions mutually meet. If they are to be distinct colors, at least one region in both sets of 3 must be either red or green. This made my search easier and whittled down the options to just 18 possibilities. I drew up a small ostomachion in MS Paint and copied it to fill the canvas. I then made liberal use of the paint bucket tool to discover that there were 18 possible ways to divide the figure into red and green regions. I then began dividing things up into blue and yellow regions. When two odd regions were unfilled, without loss of generality, I assumed they were both blue (they certainly were the same color to make the parity work out). Otherwise, I just picked a region to be blue and filled in the rest as followed. I found that every distribution of the blue and yellow regions was uniquely defined by the demand that adjacent regions be a different color and (possibly) that they have a total area of 36. This meant I didn't need to do any more combinatorics. Of the 18 regions I enumerated, nine had the areas equidistributed. If we allow for permutations of the four colors (24 total) that means there are a total of 216 different ways of filling in the ostomachion such that no adjacent regions have the same color and the area is equidistributed between the four colors, with 36 tiles of area per color. Anyone wish to check my work? I'll post my figure later, if anyone is interested.
Experienced Forum User, Published Author, Player (79)
Joined: 8/5/2007
Posts: 865
FitterSpace wrote:
The last three digits of the timer is a speedometer. I'm not sure why it replaces the digits on the timer, but i guess that's just the way they made it.
Oh, that's actually really cool.
Experienced Forum User, Published Author, Player (79)
Joined: 8/5/2007
Posts: 865
I have a feeling this has been answered before, but what's the deal with the timer in the latest video? It wasn't glitchy in the previous video you posted.
Experienced Forum User, Published Author, Player (79)
Joined: 8/5/2007
Posts: 865
Amaraticando wrote:
Bobo the King wrote:
No joke, I was thinking of doing the same thing. Then you actually went there. (By the way, is there any reason that this polynomial evaluates to an integer when x=19? Is that true in general? It seems like a wild coincidence.)
I just added the value that I wanted as the 19th term and incremented the degree of the polynomial.
Oh, oops. I should have noticed that a 17th degree polynomial can be fit to 18 points.
Experienced Forum User, Published Author, Player (79)
Joined: 8/5/2007
Posts: 865
Amaraticando wrote:
The next number s(19) is 69. This sequence clearly obeys the following polynomial:
No joke, I was thinking of doing the same thing. Then you actually went there. (By the way, is there any reason that this polynomial evaluates to an integer when x=19? Is that true in general? It seems like a wild coincidence.)
Experienced Forum User, Published Author, Player (79)
Joined: 8/5/2007
Posts: 865
This week's Riddler challenges were kind of interesting and I'm still working on the first one. The second one is mostly a matter of patience and it's pretty clear what you're supposed to do. Regarding the first one, however... I was stumped for a good long while until I loaded the image into MS Paint and flipped it vertically so that I could see precisely what was being graphed. I placed the flipped image in the upper-left corner so that the bottom-left corner of the original image corresponds to the point (0,0). I also noticed that some of the pixels have colors associated with them. I then used OEIS to find out exactly what the patterns were. Here are my findings:
  • The first row and first column contain black pixels if they are prime numbers such that p+1 is divisible by 4. I haven't yet figured out the significance of this, as it does not fit the pattern of the other rows or columns.
  • Coordinates (x,y) are black if x^2 + y^2 is prime. Incidentally, this explains why the black pixels are symmetrical about the main diagonal and why the main diagonal is white. It probably also explains why you never see five or more black pixels along any diagonal, but I'll work that out another time.
  • Colored pixels are not prime. Of course, this means they're begging to be prime factored...
  • Computing x^2 + y^2 for each colored pixel, we see that they each have exactly two distinct prime factors. (Two of the orange pixels and one of the purple pixels are divisible by 9 = 3^2.)
  • These prime factors seem to show up repeatedly. For example, the prime factors for the orange pixels are 3^2*5, 3^2*17, 5*13, and 13*17. These can be "chained" along: 3^2 --> 5 --> 13 --> 17 --> 3^2. Unfortunately, some of the primes can't be strung along in this manner and are isolated.
And at this point, I'm stuck. Any thoughts? Edit: All of the prime factors (or prime powers, in the case of 3^2) are multiples of 4 plus 1. Hmmm...
Experienced Forum User, Published Author, Player (79)
Joined: 8/5/2007
Posts: 865
Soig wrote:
For 8-6, some special actions do take effect to the auto-scroll. So it's a improvable point...
Hooray! I'm helping!
Experienced Forum User, Published Author, Player (79)
Joined: 8/5/2007
Posts: 865
In 8-6 I noticed that the scrolling is a little bit inconsistent. It appears to speed up whenever you ground pound or bounce off a wall. Is this exploitable? Edit: Also, in 8-7, at around 19:30 in the encode, would it be possible to trigger the moving platform, go back for the star, and then return to the platform?