tag:blogger.com,1999:blog-58621246919014960052024-02-07T04:55:50.134-08:00Simpleton Geek's JournalA blogspot journal showcasing computer programming, personal development, and other hobbies. Featuring Raspberry Pi, Petit Computer, and miscellaneous How-To.Harry Hardjonohttp://www.blogger.com/profile/02635313407341489264noreply@blogger.comBlogger255125tag:blogger.com,1999:blog-5862124691901496005.post-21674210037940111712022-07-31T04:00:00.001-07:002022-07-31T04:00:00.186-07:00Essay 07 A 3G Computer Specification<h2 style="text-align: left;">Essay 07 A 3G Computer Specification</h2><h3 style="text-align: left;">Minimum Specification Computer</h3><p><br /></p><p>It was sometime ago when Raspberry Pi Foundation came up with Raspberry Pi Zero. That's a bubble gum size computer, in comparison to mint tin sized computer. I think it's cute, and of course I bought one. The specification, however, falls short of my vision of an ideal computer.</p><p><br /></p><p>Of course, it would be nice to have everything, but what I'm really aiming for is a cheap computer that does good enough computing. I still keep one to use as a daily driver when travelling. Raspberry Pi Zero is such a cute and handy computer!</p><p><br /></p><p>Regarding the performance, it is somewhat lacking. It reminds me of the story of 3M computer specification. It tells a story about how Steve Jobs first heard the term.</p><p><br /></p><p> https://en.wikipedia.org/wiki/3M_computer </p><p><br /></p><p>which became the driving design of Next Computer: a megabyte of memory, a megapixel display, and a million instructions per second processing power. It is also commonly said that the price should be less than $10,000. </p><p><br /></p><p>When I define the specification of a simple yet usable computer, I came up with 3G specification: 1 GHz CPU, 1 GB RAM, and 1 Gb Bandwidth. The price should be less than $100. Raspberry Pi Zero didn't quite measure to it: 700 Mhz CPU, 512 kB RAM, and USB2 spec. So, I'd say about half my ideal specification, except the price, which was $10 with WiFi.</p><p><br /></p><p>Raspberry Pi 4, which I bought as soon as I was able upon release, was in many ways exceeds the specification by about 4 times: 4 cores of 1 GHz CPU or faster, 4 GB RAM, and USB3 bandwidth. The price is $55, quite reasonable for the power and performance. So powerful, in fact, that the only applications that I can possibly max out of it would be 3D rendering and video editing. It mostly just sit idle doing nothing most of the time.</p><p><br /></p><h3 style="text-align: left;">The Invisible Bandwidth</h3><p><br /></p><p>If you notice the difference of specification between the two, the original specification specified MIPS as an important factor. Steve Jobs puts in Display resolution as the important factor. I put Bandwidth as the important factor.</p><p><br /></p><p>The reason why I don't really care about MIPS and Display is because I don't really use them. I mostly deal with integer calculation, and as far as display resolution is concerned, I'm still stuck with 800x600 resolution. In fact, I regularly set the font to large size, so that I don't have to squint at the display. Yes, I have a large HDMI monitor. No, I'm not a member of Tiny Font Society!</p><p><br /></p><p>I set all my fonts and menu bar to large size, and I'm really dismayed that most program, including games and productivity tools, regularly set the font to extremely tiny size. Do you all have perfect vision or do you just not care? I think it's mostly the latter, but I really do hate tiny fonts.</p><p><br /></p><p>As far as Bandwidth specification is concerned, I was clued in to the difference between Personal Computer (PC) and Mainframe Computer. I really like to deal with large amount of data, and the PC works well enough, but on the mainframe computer, I noticed that the processing went by at a much faster rate than the CPU would indicate. This piqued my interest. As I pore over the literature for the difference, I notice that the bandwidth is much larger on the mainframe. There is the answer!</p><p><br /></p><p>Actually, that's not the whole story. There are several Bandwidth involved. The obvious one is the System Bus for data transfer between CPU and RAM. Then there's the bandwidth between computer and I/O devices. This is Serial, Parallel, or USB. Another set of bandwidth is the bandwidth between main CPU, math co-processor, and graphic co-processor. Nowadays, we have System on a Chip (SOC) architecture where everything is contained in one die. So, the most restrictive bandwidth is the I/O bandwidth, hence Gigabit bandwidth.</p><p><br /></p><p>Or is it? Remember that I/O stands for Input/Output. Which external device has the slowest data rate? It's not the hard disk, or network, or keyboard. The slowest most restrictive bandwidth remains ignored because it's invisible. It seems like I'm the only one in the world who works on it.</p><p><br /></p><p>The slowest bandwidth of the system is the bandwidth <i>between keyboard and chair!</i></p><div><br /></div>Harry Hardjonohttp://www.blogger.com/profile/02635313407341489264noreply@blogger.com0tag:blogger.com,1999:blog-5862124691901496005.post-22217027731377782912022-07-24T04:00:00.001-07:002022-07-24T04:00:00.175-07:00Essay06 The Core of Computer Programming (part 2)<h2 style="text-align: left;">Essay06 The Core of Computer Programming (part 2)</h2><h3 style="text-align: left;">The usage of IF-GOTO</h3><p><br /></p><p>In part one, I talk about the fundamental hardware necessary to enable IF-GOTO Conditional Branching. In part two, I will show the different way IF-GOTO can be used. Notwithstanding the exhortation "GOTO considered harmful!", let's see how Conditional Branching is to be used in a computer program.</p><p><br /></p><p>Remember that computer program lies in Memory, and that is in reality just a sequence of numbers in sequential memory addresses. Computers don't really distinguish code and data, unless the hardware store each part separately. We're not concerned about that, though.</p><p><br /></p><p>The simplest GOTO is Unconditional Branching. This is true if the Conditional evaluates a constant. In other words, either it is always True or always False. Or maybe, the Conditional isn't even checked. It has very limited usage, mainly to connect to a subroutine somewhere else. Reason maybe to simplify the main code, try to fit in the code more than what relative jump can cover, or provide hooks to be modified to point to updated code later. It can also be used to provide Infinite Loop. Lastly, it can also be abused to provide "Spaghetti Code" style of coding.</p><p><br /></p><p>Therefore, Conditional Branching imply variables in the Conditional. This can be True or False, dependent on the variables. There's a whole section of Boolean algebra regarding this, but let's not go there for now. The main consideration here is that we can skip Forward, or Loop back.</p><p><br /></p><p>Skipping Forward is usually used to provide interactive process. IF Something THEN Do This Else Do That. </p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">IF (TRUE) THEN DO THIS. <br /></span><span style="font-family: courier;">IF (FALSE THEN DO THIS.<br /></span><span style="font-family: courier;">IF (TRUE) THEN DO THIS ELSE DO THAT</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">IF (TRUE) THEN DO THIS<br /></span><span style="font-family: courier;">ELSE IF (TRUE) THEN DO THIS<br /></span><span style="font-family: courier;">ELSE IF (TRUE) THEN DO THIS<br /></span><span style="font-family: courier;">ELSE DO THAT</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>The second example is called "IF-ELSE" ladder, and you can chain them for quite a long chain. There is something similar to this structure: ON...GOTO</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">ON (var) GOTO 1,2,3,...,N<br /></span><span style="font-family: courier;">ON (var) GOSUB 1,2,3,...,N</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>In C, we use switch() { case 1: ... default; } construct. The idea is that we execute different code depending on the value of variable, instead of TRUE/FALSE. Generally speaking, this is a concept of Multiplexer/Demultiplexer. </p><p><br /></p><p>Next, consider IF-GOTO to the preceeding address. This is called a LOOP. Easy way is Infinite LOOP.</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">LOOP start:<br /></span><span style="font-family: courier;">...<br /></span><span style="font-family: courier;">...<br /></span><span style="font-family: courier;">GOTO start:</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>You can use the loop to repeat N times:</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">REPEAT<br /></span><span style="font-family: courier;">...<br /></span><span style="font-family: courier;">...<br /></span><span style="font-family: courier;">UNTIL N=10</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>In C, we use do { } while () construct.</p><p><br /></p><p>You can loop as long as a condition remains True</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">WHILE (cond)<br /></span><span style="font-family: courier;">...<br /></span><span style="font-family: courier;">...<br /></span><span style="font-family: courier;">WEND</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>In C, we use while () { } construct.</p><p><br /></p><p>There is also FOR LOOP, but it's not interesting for the discussion. What is interesting are the keywords *break* and *continue*. CONTINUE is used to skip the rest of the loop and go to start immediately, while BREAK is used to BREAK out of the loop immediately. You can think of it as GOTO Start and GOTO End.</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">LOOP Start:<br /></span><span style="font-family: courier;">...<br /></span><span style="font-family: courier;">IF (cond) GOTO End: #break<br /></span><span style="font-family: courier;">...<br /></span><span style="font-family: courier;">IF (cond) GOTO Start #continue<br /></span><span style="font-family: courier;">...<br /></span><span style="font-family: courier;">GOTO Start<br /></span><span style="font-family: courier;">End: #End of loop</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>And that should be it. There is also the Spaghetti Code style where you just go everywhere whenever you want. Such pattern are confusing and should be avoided whenever possible, but if you ever try to build a parser, maybe by using lex and yacc, then it can't be helped. State based or Functional coding is like that, too.</p><p><br /></p>Harry Hardjonohttp://www.blogger.com/profile/02635313407341489264noreply@blogger.com0tag:blogger.com,1999:blog-5862124691901496005.post-49758848092757045342022-07-16T04:00:00.003-07:002022-07-16T04:00:00.178-07:00Essay05 The Core of Computer Programming (part 1)<h2 style="text-align: left;">Essay05 The Core of Computer Programming (part 1)</h2><h3 style="text-align: left;">A look at (simplified) computer system</h3><p><br /></p><p>The question is: What is essence of computer programming? What is the core of computer programming? What is it, that if you take away from the thing that is computer programming, will cause the thing to no longer be computer programming? My answer is: Conditional Branching (IF-GOTO).</p><p><br /></p><p>This is a surprisingly deep issue. There are many considerations regarding this question. I had planned this to be just a single post, but having seen the whole, completed answer, I decided to split it into 2 parts. If you, like most people, think that the issue is a simple one, then I encourage you to stop at this point and work out your answer. Then continue reading, and compare our answers.</p><p><br /></p><p>First, let me tell you what computer is not. There is an old joke that when a prospective buyer ask a salesman what the computer can do, the salesman answered that the computer can do half the things the customer can do. "Great! I'll take two!" Ha ha. Well, computers don't work like that. Computers can only do what you tell it to do, no more, no less. And whatever the computer was told to do, the computer can do it exceedingly fast, and with great accuracy.</p><p><br /></p><p>Of course, fast is a relative term. Back on the old Apple 2 days, 1Mhz is fast, but not that fast. Yet, it is still much faster than Charles Babbage Analytical Engine. Nowadays, we have fast computers, but is it really that fast? Newer programs are such a bloat, that huge amount of computer resources are taken, not for working on the problem, but on cute animations that aren't that useful, or even cute, for that matter. So much waste.</p><p><br /></p><p>We don't really need compilers or programming language, either. Computers are basically a collection of bits and bytes. Ones and Zeros. There's really not much more to it, until we get to Quantum mechanics. We do have CPU, but what is the core difference between a programmable calculator, and a computer? In simple terms, why is The Difference Engine a calculator, while the Analytical Engine a computer?</p><p><br /></p><p>The most fundamental principle that is uniquely a computer program is, in my view, Conditional Branching. The ability to change the path of computation is fundamental of computer programming. If you have everything else except conditional branching, then you don't have a computer. What you have, then, is a batch processing. Imagine a robot that does a complicated dance, but repeatedly so without any change. Is that a robot? Yes. Is that a computer program? I'd say no. It's a complex mechanical construct, but not a computer. If, say, a car manufacturing robot can only be influenced by On and Off, then it's not a computer program, rather a batch processing. If, however, the robot can sense a car being somehow incorrectly staged and alerts the shop foreman, then it is a computer program. A computer program reacts to changing condition. A batch process cannot.</p><p><br /></p><p>The simplest implementation of Conditional Branching that I can think of is IF-GOTO. This is true regardless of computer language. It can be Branch if Zero (BZ), Branch if Not Equal (BNE), IF-THEN-ELSE, WHILE/REPEAT LOOP, and other constructs. So, what does it mean, exactly that IF-GOTO exists?</p><p><br /></p><p>Well, first of all, you need some kind of variables, and that variables can be compared. Variables means pointers. Pointers mean memory addresses to point to. Memory addresses can contain both code and data, but they are really just numbers. This means that GOTO address can be used to call functions. Combined with data stack, and you can call function recursively. You also need CPU because of the explosive combination between operation and data. CPU means you need some kind of flip-flop clock, in order for the CPU to process each instruction cleanly. </p><p><br /></p><p>The should also be some means of Input Output available. That means we need System Bus in order to shuffle data from Memory to CPU and vice-versa. We also want the computer system to interact with outside world. So, some kind of external data line, either serial, or maybe GPIO is in order. Interactive element can be Keyboard, Mouse, or Telemetry signal receiver. Output can be Display, Teletype, or maybe just some speakers.</p><p><br /></p><p>Along the way, we can optimize further with Cache Memory or Co-Processor, but all things considered, the core of computer program is IF-GOTO. The rest is just there to support that process.</p><div><br /></div>Harry Hardjonohttp://www.blogger.com/profile/02635313407341489264noreply@blogger.com0tag:blogger.com,1999:blog-5862124691901496005.post-22623756526509669302022-07-15T04:00:00.003-07:002022-07-15T04:40:57.545-07:00Essay 04 Amateur vs Professional Quality<h2 style="text-align: left;">Essay 04 Amateur vs Professional Quality</h2><h3 style="text-align: left;">Does it really matter?</h3><p><br /></p><p>I have seen it too many times. In fact, I have hardly ever seen otherwise. My development environment as well as code style is that of an amateur hobbyist. Other people, even beginner coder, would go professional from the start. The question I'm asking is: Why would you want to handicap yourself to suffer professional quality programs when a simple hobbyist tool suffice?</p><p><br /></p><p>Do you always get a race car for your daily drive? Do you always get the comprehensive tool cabinet when a tool bag gets the job done? Do you always get a professional studio when a sketchbook is handier? Why would you want to insist that a 4 GB Visual Studio is the only IDE you use, when a simple text editor will do? </p><p><br /></p><p>This kind of argument gets really bad. Adobe Studio Tools are definitely top quality, but as professional tools, they are rather expensive. GIMP and Krita are reasonable choices. Microsoft Office are great, too, but I used to just get a cheaper Microsoft Works since it gets the job done just fine. Oracle database is the best in the world, but most people can use MySQL well enough. Why would I want to use GCC with its long compile times, when TCC compiles near instantly?</p><p><br /></p><p>As a hobbyist, coding should be fun. It doesn't matter that my hobbyist program compiled with TCC runs 3 times longer than a professional code compiled with GCC. The difference between 1 second and 1/3 of a second isn't that much. The fact is, that with TCC, I don't even bother doing the compilation step. There is an option to -run the source code directly! So, that is what I have been doing. It reminds me the easy of use of Perl. Perl is even more convenient!</p><p><br /></p><p>Are the resulting program any good? I like to think so. Clayton Christensen's The Innovator's Dilemma stated: "Generally, disruptive technologies underperform established products in mainstream markets. [snip] Products based on disruptive technologies are typically cheaper, simpler, smaller, and frequently, more convenient to use." The point is, you don't have to outperform the best in the world. There are other opportunities in the smaller, niche markets. If you can't be a big fish in a big pond, then try to be a big fish in a small pond and make the pond bigger!</p><p><br /></p><p>There lies the best value of a hobbyist. We don't have to have the best of everything. We just have to have a good enough tools. We don't have to be the smartest. We just have to be not stupid. We don't have to be the cheapest. We just have to provide good value. Coding? That's easy. Design? That's hard. The hard part of a journey isn't in making it. The hard part of a journey is knowing where to go!</p><p><br /></p><p>Let's talk about professional frameworks a bit. There are many names: Xtreme, Agile, Scrum, and others. For the most part, they deal with the same issue: How to handle communication with clients. How to track progress and manage milestones. How to manage personnel involved in the project. A formal package for deliverables. There may be different philosophical and paradigm involved, but they mostly deal with the same issues.</p><p><br /></p><p>Professionals <b>need</b> to deal with those issues. Not having proper procedure to deal with those issues will negatively affect client-producer relationship. So, having to follow at least one methodology is an absolutely crucial to the process. </p><p><br /></p><p>Hobbyist, on the other hand, don't really need to do that. They are their own clients. If something goes wrong, they can just fix it themselves. They do their own program maintenance. They don't have to worry about the ignorant boss who claims that stream-lining existing code is "a waste of time" even though it will save a lot of time in maintenance later. To that end, hobbyist have the advantage of not having to watch the clock, so to speak.</p><p><br /></p><p>Expenses can be lower for hobbyist as well. Niche market which big business will never dream of entering is fair game for hobbyist. It's simple math: Less expense yields more profit, even if the overall revenue is less. </p><p><br /></p><p>So, my coding is at the amateur hobbyist level. While most people consider that as a handicap, I actually consider that as an advantage! My code is cleaner, simpler, and easier to understand. It works fast enough, and good enough to do the job well. Best of all, if there's something that is less than perfect, I'd just fix it. The source code is right there! It's easy to do because the code is simple and easy to understand. There's none of the complex framework involved as with professional quality codes. I should know, I've been both.</p><p><br /></p><p>Following the lead of Satoru Iwata: My title may be business owner. My training is that of a computer programmer. But in my heart, I am an artist. I'm not a coder who does art. I am an artist who does code.</p><p><br /></p><p><br /></p><p> </p><p><br /></p>Harry Hardjonohttp://www.blogger.com/profile/02635313407341489264noreply@blogger.com0tag:blogger.com,1999:blog-5862124691901496005.post-74633373552898243582022-07-14T04:00:00.001-07:002022-07-14T04:00:00.200-07:00Essay 3 C is misunderstood<p>Essay 3 C is misunderstood</p><p>Quirky, flawed, and tremendous success! -Dennis Ritchie</p><p><br /></p><p>Imagine, if you will, that you are living in the 1970s where computer are in the beginning of their creation. You have a simple machine with simple instruction set. And you want to program the computer. What will you do?</p><p><br /></p><p>1. Rewire the circuit</p><p>2. Enter hex numbers, backwards</p><p>3. Enter decimal codes</p><p>4. Enter mnemonic assembly</p><p>5. Use FORTRAN</p><p>6. Use Forth</p><p>7. Use BASIC</p><p><br /></p><p>Most programmers at the time use assembly programming language. Higher level construct are inefficient and to be used only by unskilled clerks. The assumption was that if you can say it in English, then you can say it in computerese. However, you do need to say it in restricted English. In other words, Pseudocode.</p><p><br /></p><p>No one code in Pseudocode, except Donald Knuth, but he's the only one to do so with his Literature Programming. However, my point is simple: Translating Pseudocode from English to high level computer language is so easy, anybody can do it!</p><p><br /></p><p>Forth, a stack based language, is unique, in that it's simple to code, yet capable of powerful functionality. You don't see Forth nowadays, but the spirit lives on PostScript format, which is contained in Portable Document Format (PDF). Another simple language is List Processing (LISP) and its dialect cousin Scheme. You may see it in Emacs scripting engine.</p><p><br /></p><p>Of course, there is BASIC and LOGO, as well. Those are mostly limited in educational institution. The thing about them is that they're easy to code. BASIC, famously, can easily fit in less than 8K. LOGO and a more sophisticated BASIC can fit in a bit more memory, such as 8K. I have personally done a LISP based interpreter in as little as 300 lines. Other students did it in about 600 lines. But I digress. The point is that creating a coding language was by necessity an exercise in small scale expenditure. Computers of the day just isn't capable of large memory footprint requirements.</p><p><br /></p><p>So, then, the question that needed to be answered at the time was "What is the most efficient way to program a computer that has the ease of high level language, yet be capable of fast machine language execution speed?" And that was the goal of the project. It began with BCPL, then a simplified version of it, B, was conceived. Then improved to C.</p><p><br /></p><p>C was never conceived to be a high level language. It amuses me to no end that people nowadays call C a high level language. Maybe C++, although that was debatable, too. You see, C++ was originally created as a precompiler that compiles to C. C++ now compiles directly to ASM to take advantage of the language construct to generate good optimization. However, at the time, C++ to C to ASM to ML was quite common. The reason being is "ease of implementation."</p><p><br /></p><p>If you have the hardware, you have Machine Language (ML). In order to ease the programming process, Assembly language (ASM) is used. C compiler compiles to ASM, which is then compiled and linked to ML. It's trivial to write an assembler. It's not difficult to write a Tiny BASIC compiler, albeit, having done so, I can testify that Tiny BASIC has a rather limited utility.</p><p><br /></p><p>So, a more powerful language was desired, and the priority is to write something that is easy to write and compile. Hence, C uses a lot of standard libraries. About the only custom library is the stdio library. That is done with machine language. Most other library actually use C.</p><p><br /></p><p>If you look at the libraries, most of them are really simple and easy to do. Once you have the core C compiler going, you can just implement the rest really, really easy. Hence, the nearly ubiquitous presence of C compiler. C compiler is relatively quick and easy to do, at least in principle, before the desire for a more powerful language comes into being.</p><p><br /></p><p>I'm not the one to discuss the merits of various C language features, but fortunately, Brian Kernighan is still alive and well, and I believe he is the de facto person to consult about such things. My point is: C language is small and easily implementable across most system, and therefore available to most computers.</p><p><br /></p><p>There is a version of C compiler called Tiny C Compiler (TCC) which I actually use every day. I don't use Gnu C Compiler (GCC) which is what professional coders use. That's because it's really overkill for my use. I only use the smallest set of C language features, anyway. Why would I want to use GCC? GCC's compilation time is rather extensive! </p><p><br /></p><p>And yet, simple as it is, C does feature rather powerful set of capabilities. It bridges the assembly language and high level language. C was actually classified as "middle level" language, yet quite powerful. There is actually a design called C--, which is an even simpler language set, but that isn't popular. In short, C occupies the ideal "Goldilocks" zone of complexity and features.</p><p><br /></p><p>That is my take of C language. It's not a language that is the end of all language, rather it is the language that is the beginning of all languages. A whole lot of later generation languages can trace its lineage to C. I already mention C++, but basically C -> C++ -> Java -> C# -> Rust is one such lineage. Another would be C -> Perl -> Raku. There are plenty more.</p><p><br /></p><p>Should you learn C? I would advise it, but not if you're a beginner. For beginners, there are more accessible language such as BASIC, which is designed for beginners in mind, about the only difficulty is the lack of unified dialect. The most popular BASIC dialect seems to be Microsoft QuickBasic, and QB64 seems to be a good implementation of it. The question you should ask is: Will you be willing to learn Assembly programming? Do you want to code as many languages as possible? Do you want to write program in various systems/hardwares? If yes, then learning C is a great way to get started!</p><p><br /></p><p>As Dennis Ritchie himself pointed out: C is quirky and flawed, but it's also tremendously successful. Yes, the standard library isn't the greatest in the world, but it's not supposed to be. They're supposed to be simple and easily implementable. If you need more, then you should code your own libraries. C makes that easy.</p><p><br /></p><p>As a note: Tiny BASIC specification features a FOR-LOOP. I'd say that's a mistake. WHILE-LOOP is easily implementable, as is REPEAT-LOOP. If you add *continue* and *break*, then you can even use infinite loop! GOTO is also useful, albeit easily misused. The answer is simple: Structured GOTO. </p><div><br /></div>Harry Hardjonohttp://www.blogger.com/profile/02635313407341489264noreply@blogger.com0tag:blogger.com,1999:blog-5862124691901496005.post-22173270034615240642022-07-13T04:00:00.004-07:002022-07-13T08:40:58.067-07:00Essay 2A "Mechanic" Computer Programmer<p>Essay 2 A "Mechanic" Computer Programmer</p><p>Not insulting Mechanical Mechanics</p><p><br /></p><p>My frame of reference for this piece, is that of a magical circle. By which I mean magicians, either performing on stage or street magicians. If you want to know the secrets of magicians, all you have to do is go to a magic store, and there you will find gadgets galore, all ready to fulfill all your magical needs.</p><p><br /></p><p>There are tricks, however, that is unachievable by magical gimmicks alone. Certain magic tricks require the magicians to perform with skill, either misdirection, or hidden manipulation. It can take years to refine those skills, and it's certainly no easy feat to be an accomplished magicians.</p><p><br /></p><p>However, there are magicians who decided that skills are beyond them, and they depend on gimmicks for their performance. The term bandied about is "mechanic", which as you may surmise, a rather dim view of the quality of their magic. Yes, they are magicians, but no, not a high level, or even medium level ones. In short, "mechanic" magicians are mediocre magicians.</p><p><br /></p><p>Those magicians are usually get hired at children parties. Children, being inexperience in ways of the world, tend to be immune to misdirection. Only the greatest magicians can pull off successful misdirection with children, and most magicians who depend on these children parties wisely chose mechanical magic for their entertainment. Furthermore, if you want to entice these children to become magicians in the future, you would be well advised to keep a few of these gimmicks as to inspire them to the wonders of magic.</p><p><br /></p><p>However, they should at least keep trying to attain higher skill levels. Those who doesn't generally receive well-deserved scorn for their performance. There's nothing new in their performance. No need for them to divulge their magical secret. Just go to the store and buy their tricks! No real value to their craft.</p><p><br /></p><p>Now, imagine that you are a computer programmer. You learned so many things. Maybe Java or C#. PHP or Python. HTML, CSS, and JavaScript? Sure. You learn so many frameworks and paradigm. Pair Programming, Agile, and Patterns? Why not? Why not use the most powerful tools available? After all, professionals use them, so why not give yourself the same advantage those professionals use? Why handicap yourself to primitive ones?</p><p><br /></p><p>The thing is, I don't think primitive tools are handicaps. I think powerful tools are crutches. They allow you to do great things with their "black box" solution, so to speak. There is a difference between knowing how to do things and use code libraries to do them, and use code libraries without understanding what they do, or how they do things. </p><p><br /></p><p>Somebody ask me once, why does it matter to use code library if they can recreate the library from scratch? "Nothing," I answered, "but the problem is that they cannot recreate even the simplest task!" That is the problem. It's not that using code library is a problem, but the lack of ability to be independent of them that is the problem.</p><p><br /></p><p>Nowadays, such questions aren't even asked anymore. Whenever you see computer programming course, you see a ton of these names of these technologies spread around with no regards of how they're made. As more and more of these courses ignore the underlying technologies, the myth of the difficulty of computer programming become more and more exaggerrated. Nowadays, people have no problem claiming that Turtle graphic is an absolute impossibility to teach to students. We're talking about Forward, Turn Left, Turn Right, and PenUp/PenDown! It's so simple, that I've done it in 10 minutes. Somehow, their inability to code Turtle Graphic becomes <i>nobody</i> can code Turtle Graphic easy and that it takes years to do!</p><p><br /></p><p>Somebody actually told me with a straight face, that "include FizzBuzz" is a perfectly acceptable solution to the problem. And don't tell me about the numerous "professional" programmers, who would be happy to remove recursion from Quicksort() by using Stack() routine! Uh-huh. They just turn implicit stack into explicit one. How is that any better?</p><p><br /></p><p>I was 13 years old when I independently learned how to use sin() and cos() to draw a circle. I then proceeded to write Spirograph type of programs. It's not until much later in the latter part of my high school senior year in AP Calculus class, that the teacher taught the exact same subject. Needless to say, I scored 100%. The thing is, it seems like nobody else thought that it was easy, judging by the expression of their face and the way they look at me. And these are the smart kids. I'd have thought that maybe lots of them would get it as well, but apparently not.</p><p><br /></p><p>I think more important that the ability to learn from a teacher in a classroom is more important than the ability to get as many certifications as possible. It takes independent thinking, and that takes guts, as well as stubbornness to try to dissect pre-existing code libraries and to try to figure out how they do things. It takes curiosity, problem solving skills, and the willingness to suffer the inevitable frustration as you try to decipher professional code.</p><p><br /></p><p>I don't think I want to suffer the pain of deciphering professional code. The few times I did, I end up with reducing the code size, usually to 25% of the original size. I think most of professional coder are Rube Goldberg practitioner. I have no patience for that. What usually happen of late is that I would figure out the API, which tells me the functions and capability of the library, and I will figure out the appropriate Data Structure involve. After that, the code will usually write itself.</p><p><br /></p><p>The point I'm making is that if I can be independent from Other People's Code, then I would do so. There's nothing more assuring that the code you have is the most fool-proof, correct code possible because you write it yourself. After all, who wants to dedicate the most time writing the correct code for you if not yourself? Nobody, that's who!</p><p><br /></p><p>You can always ignore this advice, and constraint yourself to a programming language and libraries. Sure, you can do that. But then, you will feel the same pain I felt when I moved away from Linux/Perl solution to Windows environment! When I decided to rebuild everything from scratch, I found out, to my dismay, that most of them are really OS calls, and that I needed to rebuild the most of OS from scratch! Perusing GNU source code didn't help. Did I say that they're complicated? They're complicated! So, it was really a pain!</p><p><br /></p><p>Nowadays, I'm using Raspberry Pi, and that's Debian technology. So, that's fine. But I already moved away from Perl. I'm building my own set of libraries to do, and I don't regret the extended amount of time I spend building it. After all, I only have to do it _once._</p><p><br /></p><p>So, you can try your best to study, really study, the whole spectrum of computer programming. Or you can be a mechanic. Your choice.</p><div><br /></div>Harry Hardjonohttp://www.blogger.com/profile/02635313407341489264noreply@blogger.com0tag:blogger.com,1999:blog-5862124691901496005.post-25778970211205089032022-07-12T04:00:00.003-07:002022-07-12T04:00:00.188-07:00Essay 02: Why do we code?<h2 style="text-align: left;">Essay 02: Why do we code?</h2><p><br /></p><p>Why do we code? I don't know. I mean, I know why I code, by why would anyone else want to learn to code? I think the best answer came from Steve Job: "I think everyone in this country should learn to code, because it teaches you how to think." And what a fine answer it is! </p><p><br /></p><p>Unfortunately, the Apple Macintosh, in fact, did not come with a built-in programming language. You had to buy an Apple Lisa system, at $10,000, to write a program for the Macintosh. Great user interface, but programming for it is rather a painful experience!</p><p><br /></p><p>So, here are some ideas on why you should learn to code, and my reaction to them:</p><p><br /></p><p>1. Logical Thinking. Also known as left-brain function. And yet, I have seen computer programmers use their right-brain side. Rather emotional. Artists tend to be that way. Steve Jobs, for example, did not do any heavy duty coding. Sure, he knew how to code, but he didn't do it professionally. He relegates himself as visionary, and that requires more than logical thinking. It requires imagination and intuition. As well, people can and do develop logical thinking without learning computer programming. The ability to reason isn't an exclusive domain to computer programmer. Chess players, for example, can do it, too.</p><p><br /></p><p>2. Creativity. I doubt that. I think people are either creative or not. The creative ones can and do well in computer programming. However, I have seen too many people just use other people's code, without thinking whatsoever. Only in the bleeding edge of technology that creativity is rewarded. However, that area of research isn't too common. As far as art is concerned, there is Creative Coding and Generative Art, but those are rather rare.</p><p><br /></p><p>3. Resilient and Perseverance. The ability to weather hard times, so to speak. I find that hard to believe. As soon as people see code, their mind go blank, and they never pick up coding. Those who sticks with it would be amply rewarded, sure, but so is sticking with Karate to develop discipline, so to speak. Just as creativity is a talent, so is perseverance.</p><p><br /></p><p>4. Communication skill. This I agree completely. Many people say that in order to be able to program a computer, you need to be good at math. The truth is, you don't. However, you do need to have good communication skill. The ability to articulate your thought, put it down on paper, and code it into the computer is an indispensable skill, and you have to have it in order to be a successful coder. Math? Do you know that coding used to be thought of as "clerical" job?</p><p><br /></p><p>5. Analytical Problem Solving. This is also true. The biggest roadblock people have in computer programming is the inability to properly recognize the problem! Defining a problem is a very necessary skill, and not too many people have it. Then, you need to be able to decide on how to solve the problem. So, yes, this is a skill and not a talent.</p><p><br /></p><p>6. Coding is fun. Well, no. Creating a computer program from nothing is a worthy endeavor and should be encouraged. But it is not a fun activity. Too many people are having trouble debugging their program, and what if there is no help available? It can be maddening experience, indeed! Tearing your hair off in frustration is a rather common experience, I'm afraid.</p><p><br /></p><p>7. Learn how to learn. Having done it, I can categorically say that learning how to learn and computer programming are not related to each other. That is, to say, if you learn how to learn and can pick up new programming language quickly, then you're well and good to progress as computer programmer. However, just because a lot of successful computer programmer can do so, it doesn't mean that the skill is guaranteed. Those are two different things.</p><p><br /></p><p>8. Money. This is also not true. I see too many job offers as needing so many years of experience in a particular platform. Also, new platforms keep coming up every year. What was good, won't be. Programming languages come and go. About the only steady job that I see is Database System Administrator. You don't need computer programming for that. Just learn SQL, and some system administrator skills. That requires certification, not boot camp.</p><p><br /></p><p>9. Prestige. All I can think of about this, is "EA Spouse", the deservedly lambasted activity for treating computer programmer shabbily. Only to be repeated at Rockstar Games, forcing their computer programmers to work a punishing 100 hours per week! Only to be let go after the game was done. All it does is burn out a lot of computer programmer. I don't see this being different anytime soon.</p><p><br /></p><p>10. Be smarter. Not at all. There is this rather popular process of testing computer programmer with "LeetCode", that is asking the job applicant to code a programming problem. The problem with that practice is that the applicant cannot use a computer or look up stuff either on books or anywhere including the web! So, obviously, the most successful applicants are the ones where they successfully memorized as many of these as possible. I have seen the question compilation and most of them are totally worthless! Either they can solve it because they've seen it before, or they can't because they haven't seen it before. All it does is gatekeep the really smart programmer (never memorize what you can look up -Einstein, Feynman, and others), and value memorization rather than smarts. </p>Harry Hardjonohttp://www.blogger.com/profile/02635313407341489264noreply@blogger.com0tag:blogger.com,1999:blog-5862124691901496005.post-50432657241971495252022-07-11T07:00:00.003-07:002022-07-11T07:50:12.144-07:00Essay 1: Introduction<h2 style="text-align: left;">Essay 1: Intro to 100 Days of Code</h2><h3 style="text-align: left;">A journey of 10,000 steps begin with the first one</h3><p><br /></p><p>One fine day, warm and sunny, I decided to take up the 100 Days of Code challenge. This was shortly after I joined Twitter and found out that there are all kinds of groups over there. Elon Musk was in the process of buying Twitter and so I decided to join. Neil Gaiman is active there, too. Well, one thing led to another and I was looking over the hashtags and found one that says "100DaysOfCode" and was sufficiently intriqued.</p><p><br /></p><p>So, I looked over the tweets, and found out that most of them does not feature any source code. And I may have missed it, but the point of doing 100 Days of Code challenge is to improve yourself, and part of that challenge is to publish the source code and share it with the world. The few that did take screenshot of their code do so with their favorite IDE, which inevitably means tiny, tiny font. Extremely hard to read. May as well not bother.</p><p><br /></p><p>The suggestion was to publish your code on Github, and there's nothing wrong with that suggestion. I do have a blog account that I still post from time to time, and so I decided to just post it there. As long as it's available, no problem!</p><p><br /></p><p>Most people actually have some kind of planning, either a book, or maybe, an on-line course. The name Angela Yu is featured with many of the posts. Another favorite of people is LeetCode. As for me, I don't have any established plan whatsoever. So, most of my time is spent trying to find the next feasible projects. The constant worry is running out of ideas to try.</p><p><br /></p><p>The point of this challenge is to learn, and I decided to learn. That means taking something out that I'm uncomfortable with and improve upon it. As of this writing, 3 weeks into the challenge, it's been mixed projects so far. Leetcode challenges are there, but I actually skip most of them because I want to write actual, usable programs. That's a tall order, as I found out that just implementing the command line parameters alone would take upwards half an hour or so. That's just setting variables, no actual program coding.</p><p><br /></p><p>As to the actual coding, I firmly believe that most of the program's core are actually very simple. To that end, I would screen capture the code from my blog, which means no tiny font! So far, I've been managing to do so in one screen. Exception is the SVG library, which is rather extensive, even in the first incarnation.</p><p><br /></p><p>The best part of taking this challenge, however, is that it anchors my day. Excepting rest days, which is Sunday, I always code. If the time is lacking, then I code something simple, such as FizzBuzz. Overall, though, it has been extremely productive sessions. </p><p><br /></p><p>And that's the real benefit of the process. My coding skill is getting better every day. Of course, it wasn't lacking to begin with, but doing this challenge forces me to be extremely productive with my time. So far, I've been spending about 2-4 hours per day, including write ups. I'm happy with the progress I'm making, especially since other people would code a challenge, and I would code a whole program.</p><p><br /></p><p>That cannot be overstated: I wrote a whole new program everyday! Not a little function, but a whole program! Now, the program maybe rough and in need of revising, which I will do as needed later. Also, there may be bugs or missing feature which means I spent some time fixing the bugs, especially if it's a program I'll be using later on the challenge. It's still a program a day, though.</p><p><br /></p><p>That just goes to show, no matter how skillful you are, there will always be higher mountain to climb, and I have begun making my steps, one day at a time. Today, it's the 18th day, and I'm resting and writing this stream of conciousness for the time to reflect back from the day of completion.</p><p><br /></p><p>2022 July 03</p><p><br /></p>Harry Hardjonohttp://www.blogger.com/profile/02635313407341489264noreply@blogger.com0tag:blogger.com,1999:blog-5862124691901496005.post-28006887681870767582022-07-10T04:00:00.004-07:002022-07-10T04:00:00.180-07:00Day 24/100 Turtle3<h2 style="text-align: left;">Day 24/100 Turtle3</h2><h3 style="text-align: left;">Look! An animated Turtle!</h3><p><br /></p><p>This is just a simple improvement for the Turtle graphic program. I had planned on having multi-turtle going, but the truth is, I also wanted to have some kind of font system going. Unfortunately, I'm really tired at the end of the week, and so decided to just implement one easy, yet eye catching feature: Animation.</p><p><br /></p><p>SVG standard actually does have animation option, but I'm still fuzzy on the details, so for this one, I decided on animating it the hard way: animated GIF.</p><p><br /></p><p>Fortunately, it's quite easy to do. All I have to do is to generate a series of frames and then use Image Magick convert program to generate the animated GIF. It will also resize the images automatically. This is the command that I use:</p><p><br /></p><p><span style="font-family: courier;"></span></p><blockquote><span style="font-family: courier;">time convert -delay 20 -loop 0 Frame*.svg -resize 320x200 FrameAnim.gif</span></blockquote><p></p><p><br /></p><p>It takes about 30 seconds to do 23 SVGs animation, so not too speedy. However, for small animation picture, that is acceptable. I do wonder why it takes somewhat long to build a 64kB image.</p><p><br /></p><p>As to the actual code, it is extremely simple. I have already done a simple SVG generator, and all I did was generate SVGs one after the other. There is a line separator marked with desired filename. This is the code that is used to cause the Turtle to write the separator:</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (!strncmp("WF",s1,2)) {<br /></span><span style="font-family: courier;"> printf("WRITE FILE %s\n",s2);<br /></span><span style="font-family: courier;"> }</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>And that's it. If you remember the Day 16/100 SplitCat program, that is the one being used to split the file into separate ones. Quite a convenience. All it takes is a one liner "WF" to write the files. Okay, I also have to set a string for the filename, and incrementing the counter. I considered having it done internal to the Turtle, but in the end decided against it for transparency considerations. Here's the code:</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> for (i=40;i<=90;i+=10) {<br /></span><span style="font-family: courier;"> for (j=60;j<=120;j+=20) {<br /></span><span style="font-family: courier;"> sprintf(FN,"Frame%02d.svg",c++);<br /></span><span style="font-family: courier;"> Turtle("WF",FN,0,0);<br /></span><span style="font-family: courier;"> Turtle("SC","",0,0);<br /></span><span style="font-family: courier;"> DrawCMYK(i,j);<br /></span><span style="font-family: courier;"> Turtle("sc","",0,0);<br /></span><span style="font-family: courier;"> }}</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>So, one line to set the string, and another to write the separator. Two lines total. And that is it for this week. Just a simple Turtle enhancement that will hopefully pay dividends down the road.</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">#include <stdio.h><br /></span><span style="font-family: courier;">#include <stdlib.h><br /></span><span style="font-family: courier;">#include <string.h><br /></span><span style="font-family: courier;">#include <math.h><br /></span><span style="font-family: courier;">#include <stdlib.h></span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">#define MAXENTRY 10000<br /></span><span style="font-family: courier;">#define MAXSTR 2560<br /></span><span style="font-family: courier;">#define sx0 0<br /></span><span style="font-family: courier;">#define sx1 118<br /></span><span style="font-family: courier;">#define sy0 0<br /></span><span style="font-family: courier;">#define sy1 180<br /></span><span style="font-family: courier;">#define PI 3.141528</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">char Liner[MAXSTR];<br /></span><span style="font-family: courier;">char Data[MAXENTRY][MAXSTR];<br /></span><span style="font-family: courier;">int numentry;<br /></span><span style="font-family: courier;">int Debug=0;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">//turtle<br /></span><span style="font-family: courier;">char co; //command<br /></span><span style="font-family: courier;">int nu; //Number<br /></span><span style="font-family: courier;">int he; //heading<br /></span><span style="font-family: courier;">int di; //distance<br /></span><span style="font-family: courier;">float an; //angle (rad)<br /></span><span style="font-family: courier;">float tx0,ty0,tx1,ty1; //line<br /></span><span style="font-family: courier;">int pe; //pen color<br /></span><span style="font-family: courier;">int bg; //background color<br /></span><span style="font-family: courier;">int mode=0; //0-normal 1-fill<br /></span><span style="font-family: courier;">char FontFam[MAXSTR];<br /></span><span style="font-family: courier;">int FontSiz;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">float map(float x0,float x1, float x2,float y0, float y2) {<br /></span><span style="font-family: courier;"> return y0+((x1-x0)*(y2-y0)/(x2-x0)); //y1<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void SVGHeader() {<br /></span><span style="font-family: courier;"> puts("<svg xmlns:xlink=\"http://www.w3.org/1999/xlink\" <br /></span><span style="font-family: courier;">style=\"fill-opacity:1; color-rendering:auto; <br /></span><span style="font-family: courier;">color-interpolation:auto; text-rendering:auto; <br /></span><span style="font-family: courier;">stroke:black; stroke-linecap:square; <br /></span><span style="font-family: courier;">stroke-miterlimit:10; shape-rendering:auto; <br /></span><span style="font-family: courier;">stroke-opacity:0.4; fill:black; <br /></span><span style="font-family: courier;">stroke-dasharray:none; font-weight:normal; <br /></span><span style="font-family: courier;">stroke-width:0.25; font-family:'Dialog'; font-style:normal; <br /></span><span style="font-family: courier;">stroke-linejoin:miter; font-size:12px; <br /></span><span style="font-family: courier;">stroke-dashoffset:0; image-rendering:auto;\" </span><span style="font-family: courier;"><br /></span><span style="font-family: courier;">width=\"128.0mm\" height=\"190.0mm\" <br /></span><span style="font-family: courier;">viewBox=\"0 0 128.0 190.0\" </span><span style="font-family: courier;"><br /></span><span style="font-family: courier;">xmlns=\"http://www.w3.org/2000/svg\"><br /></span><span style="font-family: courier;"><!--Template generated by the Batik Graphics2D SVG Generator--><br /></span><span style="font-family: courier;"><defs id=\"genericDefs\" /></span><span style="font-family: courier;"><br /></span><span style="font-family: courier;"><g><br /></span><span style="font-family: courier;"><line x1=\"10.0\" y1=\"10.0\" x2=\"118.0\" y2=\"10.0\" /><br /></span><span style="font-family: courier;"><line x1=\"118.0\" y1=\"10.0\" x2=\"118.0\" y2=\"180.0\" /><br /></span><span style="font-family: courier;"><line x1=\"10.0\" y1=\"180.0\" x2=\"118.0\" y2=\"180.0\" /><br /></span><span style="font-family: courier;"><line x1=\"10.0\" y1=\"180.0\" x2=\"10.0\" y2=\"10.0\" /></span><span style="font-family: courier;"><br /></span><span style="font-family: courier;">");<br /></span><span style="font-family: courier;">}</span></div><span style="font-family: courier;"><br />void SVGFooter() {<br />puts("<br /></g><br /></svg><br />");<br />}</span></blockquote><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void SVGDrawLine(float x0,float y0,float x1,float y1) {<br /></span><span style="font-family: courier;"> int t;</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (mode==1) {<br /></span><span style="font-family: courier;"> if (pe) {<br /></span><span style="font-family: courier;"> printf("L %f,%f ",x1,y1);<br /></span><span style="font-family: courier;"> } else {<br /></span><span style="font-family: courier;"> printf("M %f,%f ",x1,y1);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> } else if (pe) {<br /></span><span style="font-family: courier;"> printf("<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" />\n",<br /></span><span style="font-family: courier;"> x0,y0,x1,y1);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;">}</span></div><p style="text-align: left;"></p></blockquote><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int Turtle(char s1[], char s2[], int n1, int n2) {<br /></span><span style="font-family: courier;"> if (!strncmp("SC",s1,2)) { //Capture SVG<br /></span><span style="font-family: courier;"> SVGHeader();<br /></span><span style="font-family: courier;"> if (Debug) puts("SVGStart");<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("sc",s1,2)) { //Close SVG<br /></span><span style="font-family: courier;"> SVGFooter();<br /></span><span style="font-family: courier;"> if (Debug) puts("SVGEnd");<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("F",s1,1)) { //forward absolute<br /></span><span style="font-family: courier;"> di=n1;<br /></span><span style="font-family: courier;"> if (Debug) printf("Forward Absolute %d\n",di);<br /></span><span style="font-family: courier;"> an=map(0.0,(float)he,360.0,0,2*PI);<br /></span><span style="font-family: courier;"> tx1=tx0+(float)di*sin(an);<br /></span><span style="font-family: courier;"> ty1=ty0-(float)di*cos(an);<br /></span><span style="font-family: courier;"> SVGDrawLine(tx0,ty0,tx1,ty1);<br /></span><span style="font-family: courier;"> tx0=tx1;ty0=ty1;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("f",s1,1)) { //forward relative<br /></span><span style="font-family: courier;"> di+=n1;<br /></span><span style="font-family: courier;"> if (Debug) printf("Forward Relative %d\n",di);<br /></span><span style="font-family: courier;"> an=map(0.0,(float)he,360.0,0,2*PI);<br /></span><span style="font-family: courier;"> tx1=tx0+(float)di*sin(an);<br /></span><span style="font-family: courier;"> ty1=ty0-(float)di*cos(an);<br /></span><span style="font-family: courier;"> SVGDrawLine(tx0,ty0,tx1,ty1);<br /></span><span style="font-family: courier;"> tx0=tx1;ty0=ty1;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("G",s1,1)) { //Goto XY Absolute<br /></span><span style="font-family: courier;"> tx1=n1; ty1=n2;<br /></span><span style="font-family: courier;"> SVGDrawLine(tx0,ty0,tx1,ty1);<br /></span><span style="font-family: courier;"> tx0=tx1;ty0=ty1;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("g",s1,1)) { //Goto XY Relative<br /></span><span style="font-family: courier;"> tx1=tx0+n1; ty1=ty0+n2;<br /></span><span style="font-family: courier;"> SVGDrawLine(tx0,ty0,tx1,ty1);<br /></span><span style="font-family: courier;"> tx0=tx1;ty0=ty1;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("H",s1,1)) { //Heading Absolute<br /></span><span style="font-family: courier;"> he=n1;<br /></span><span style="font-family: courier;"> if (Debug) printf("Heading Relative %d\n",he);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("h",s1,1)) { //Heading Relative<br /></span><span style="font-family: courier;"> he+=n1;<br /></span><span style="font-family: courier;"> if (Debug) printf("Heading Relative %d\n",he);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("C",s1,1)) { //Color Stroke<br /></span><span style="font-family: courier;"> pe=n1;<br /></span><span style="font-family: courier;"> if (Debug) printf("Pen color %d\n",pe);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("c",s1,1)) { //Color Fill<br /></span><span style="font-family: courier;"> bg=n1;<br /></span><span style="font-family: courier;"> if (Debug) printf("Background color %d\n",pe);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("T",s1,1)) { //Font Fam+Siz<br /></span><span style="font-family: courier;"> strcpy(FontFam,s2);<br /></span><span style="font-family: courier;"> FontSiz=n1;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("t",s1,1)) { //Draw text<br /></span><span style="font-family: courier;"> printf("<text x=\"%d\" y=\"%d\" font-family=\"%s\" font-size=\"%d%%\" >"<br /></span><span style="font-family: courier;"> ,n1,n2,FontFam,FontSiz);<br /></span><span style="font-family: courier;"> printf("%s",s2);<br /></span><span style="font-family: courier;"> printf("</text>\n");<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("M1",s1,2)) { //Mode 1 start<br /></span><span style="font-family: courier;"> mode=1;<br /></span><span style="font-family: courier;"> if (bg) {<br /></span><span style="font-family: courier;"> printf("<path stroke=\"#%6X\" fill-rule=\"evenodd\" fill=\"#%6X\" d=\"\n"<br /></span><span style="font-family: courier;"> ,pe,bg);<br /></span><span style="font-family: courier;"> } else {<br /></span><span style="font-family: courier;"> printf("<path stroke=\"#%6X\" fill-rule=\"evenodd\" fill=\"none\" d=\"\n"<br /></span><span style="font-family: courier;"> ,pe,bg);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> printf("M %f,%f ",tx0,ty0);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("m1",s1,2)) { //Mode 1 end<br /></span><span style="font-family: courier;"> mode=0;<br /></span><span style="font-family: courier;"> puts("\" />");<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("WF",s1,2)) {<br /></span><span style="font-family: courier;"> printf("WRITE FILE %s\n",s2);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int Init() {<br /></span><span style="font-family: courier;"> co=' ';<br /></span><span style="font-family: courier;"> nu=0; //Number<br /></span><span style="font-family: courier;"> he=0; //heading<br /></span><span style="font-family: courier;"> di=0; //distance<br /></span><span style="font-family: courier;"> an=0; //angle (deg)<br /></span><span style="font-family: courier;"> tx0=59;ty0=90; //line from<br /></span><span style="font-family: courier;"> tx1=tx0;ty1=ty0; //line to<br /></span><span style="font-family: courier;"> pe=1; //pen<br /></span><span style="font-family: courier;"> strcpy(FontFam,"PibotoThin");<br /></span><span style="font-family: courier;"> FontSiz=10;<br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void DrawCMYK(int x, int y) {<br /></span><span style="font-family: courier;"> Turtle("C","",0x000000,0);<br /></span><span style="font-family: courier;"> Turtle("G","",x,y);</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> Turtle("C","",0x010101,0);<br /></span><span style="font-family: courier;"> Turtle("c","",0x88FFFF,0); //cyan<br /></span><span style="font-family: courier;"> Turtle("M1","",0,0);<br /></span><span style="font-family: courier;"> Turtle("G","",x,10);<br /></span><span style="font-family: courier;"> Turtle("G","",10,10);<br /></span><span style="font-family: courier;"> Turtle("G","",10,y);<br /></span><span style="font-family: courier;"> Turtle("G","",x,y);<br /></span><span style="font-family: courier;"> Turtle("m1","",0,0);<br /></span><span style="font-family: courier;"> Turtle("C","",0x010101,0);<br /></span><span style="font-family: courier;"> Turtle("c","",0xFF88FF,0); //magenta<br /></span><span style="font-family: courier;"> Turtle("M1","",0,0);<br /></span><span style="font-family: courier;"> Turtle("G","",x,10);<br /></span><span style="font-family: courier;"> Turtle("G","",118,10);<br /></span><span style="font-family: courier;"> Turtle("G","",118,y);<br /></span><span style="font-family: courier;"> Turtle("G","",x,y);<br /></span><span style="font-family: courier;"> Turtle("m1","",0,0);<br /></span><span style="font-family: courier;"> Turtle("C","",0x010101,0);<br /></span><span style="font-family: courier;"> Turtle("c","",0xFFFF88,0); //yellow<br /></span><span style="font-family: courier;"> Turtle("M1","",0,0);<br /></span><span style="font-family: courier;"> Turtle("G","",x,180);<br /></span><span style="font-family: courier;"> Turtle("G","",10,180);<br /></span><span style="font-family: courier;"> Turtle("G","",10,y);<br /></span><span style="font-family: courier;"> Turtle("G","",x,y);<br /></span><span style="font-family: courier;"> Turtle("m1","",0,0);<br /></span><span style="font-family: courier;"> Turtle("C","",0x010101,0);<br /></span><span style="font-family: courier;"> Turtle("c","",0x888888,0); //black<br /></span><span style="font-family: courier;"> Turtle("M1","",0,0);<br /></span><span style="font-family: courier;"> Turtle("G","",x,180);<br /></span><span style="font-family: courier;"> Turtle("G","",118,180);<br /></span><span style="font-family: courier;"> Turtle("G","",118,y);<br /></span><span style="font-family: courier;"> Turtle("G","",x,y);<br /></span><span style="font-family: courier;"> Turtle("m1","",0,0);<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int ProcessData() {<br /></span><span style="font-family: courier;"> char Command[MAXSTR];<br /></span><span style="font-family: courier;"> char Value[MAXSTR];<br /></span><span style="font-family: courier;"> int Num1=0;<br /></span><span style="font-family: courier;"> int Num2=0;<br /></span><span style="font-family: courier;"> int i,j;<br /></span><span style="font-family: courier;"> int c=0;<br /></span><span style="font-family: courier;"> char FN[MAXSTR];</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> for (i=40;i<=90;i+=10) {<br /></span><span style="font-family: courier;"> for (j=60;j<=120;j+=20) {<br /></span><span style="font-family: courier;"> sprintf(FN,"Frame%02d.svg",c++);<br /></span><span style="font-family: courier;"> Turtle("WF",FN,0,0);<br /></span><span style="font-family: courier;"> Turtle("SC","",0,0);<br /></span><span style="font-family: courier;"> DrawCMYK(i,j);<br /></span><span style="font-family: courier;"> Turtle("sc","",0,0);<br /></span><span style="font-family: courier;"> }}<br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int main (int argc, char *argv[] ) {<br /></span><span style="font-family: courier;"> int n,i;<br /></span><span style="font-family: courier;"> Init();<br /></span><span style="font-family: courier;"> ProcessData();<br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>One last parting thought: I will do something drastic next week. I have been delaying it for some time, and truthfully, I can stay in the same format for some more weeks, but I think it's time for me to incorporate graphical user interface. Since I'm using Raspberry Pi, it's not the easiest thing to do. So, we'll see.</p><p><br /></p>Harry Hardjonohttp://www.blogger.com/profile/02635313407341489264noreply@blogger.com0tag:blogger.com,1999:blog-5862124691901496005.post-8787312964027648682022-07-09T04:00:00.005-07:002022-07-09T18:03:55.389-07:00Day 23/100 Steganography<h2 style="text-align: left;">Day 23/100 Steganography</h2><h3 style="text-align: left;">How do you say Steganosaurus?</h3><p><br /></p><p>I've been working on this source code packager on and off. The whole idea for this program is that most forums on the web restrict the filesize for text, while allowing generous allowance for pictures. So, the idea of including text inside the picture was born.</p><p><br /></p><p>There are several different ways to do this. You can simply draw the text in the picture, which is what I have been doing. You can encode the text as barcodes or QR codes. Or you can encode the text as black and white dots.</p><p><br /></p><p>However, those solution involves creating pictures in such an ugly way. So, what if you can just include the text inside the picture itself? Hidden text, so to speak. Hence steganography.</p><p><br /></p><p>In my case, I decided that since I'm using Raspberry Pi, the display can only show 16 bit color, whereas pictures are usually 24 bit color. So, it is obvious that I should design it as one byte per pixel. The problem is that I cannot just append a byte on the picture. I have to split it as 3-2-3 bits to fit into the 5-6-5 rgb scheme.</p><p><br /></p><p>It took some doing. I made it easy for myself by skipping PNG format and go for PPM (P6) format. You're going to have to convert it to PNG format, but I'll leave that up to you. Personally, I use ImageMagick convert program.</p><p><br /></p><p>This is to Write to the image:</p><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> bit=(char) fgetc(fpImg);<br /></span><span style="font-family: courier;"> bit&=0xF8; bit|=(c&0xE0)>>5; bit1=bit;<br /></span><span style="font-family: courier;"> bit=(char) fgetc(fpImg);<br /></span><span style="font-family: courier;"> bit&=0xFC; bit|=(c&0x18)>>3; bit2=bit;<br /></span><span style="font-family: courier;"> bit=(char) fgetc(fpImg);<br /></span><span style="font-family: courier;"> bit&=0xF8; bit|=(c&0x07); bit3=bit;<br /></span><span style="font-family: courier;"> printf("%c%c%c",bit1,bit2,bit3);</span></div><p><br /></p><p>And this is to Read from the image:</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> for (i=0;i<l;i++) {<br /></span><span style="font-family: courier;"> bit1=(char) fgetc(fpImg);<br /></span><span style="font-family: courier;"> bit2=(char) fgetc(fpImg);<br /></span><span style="font-family: courier;"> bit3=(char) fgetc(fpImg);<br /></span><span style="font-family: courier;"> sout= ((bit1 & 0x07)<<5)<br /></span><span style="font-family: courier;"> | ((bit2 & 0x03)<<3)<br /></span><span style="font-family: courier;"> | ((bit3 & 0x07));<br /></span><span style="font-family: courier;"> putchar(sout);<br /></span><span style="font-family: courier;"> }</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>If you're wondering why the sout character isn't set to zero before reading in the data, that's because it's not necessary. sout is a character of 8 bits. I'm reading in 8 bits. So, sout variable is going to be wholly overwritten, anyway.</p><p><br /></p><p>I was able to use the same program for both Write and Read. Depending whether you supply both picture name and data filename, or just the picture name, the program will select the operation appropriately.</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (argc<2) {<br /></span><span style="font-family: courier;"> puts("Write: fileglob [picname.ppm] [datafilename]");<br /></span><span style="font-family: courier;"> puts("Read: fileglob [picname.ppm]");<br /></span><span style="font-family: courier;"> puts("ppm is P6 file (binary)");<br /></span><span style="font-family: courier;"> return 1;<br /></span><span style="font-family: courier;"> }</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>The hardest part is design, and trying to decipher PPM format. I still have trouble, and I'm not at all sure that I have it. The specification stated that there should be a whitespace (usually newline) after the colordepth, but it gave me an off-by-one error which shifted the color of the picture. I don't think I quiet get it, yet. So, I can only guarantee that the program <i>works on my machine.</i></p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">#include <stdio.h><br /></span><span style="font-family: courier;">#include <stdlib.h><br /></span><span style="font-family: courier;">#include <string.h></span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">#define MAXSTR 256<br /></span><span style="font-family: courier;">FILE *fpImg;<br /></span><span style="font-family: courier;">FILE *fpDat;<br /></span><span style="font-family: courier;">char buff[MAXSTR];<br /></span><span style="font-family: courier;">int w,h,d;<br /></span><span style="font-family: courier;">long l;<br /></span><span style="font-family: courier;">char sname[MAXSTR];</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int Init(int argc, char *argv[]) {</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if ((fpImg=fopen(argv[1],"r"))==NULL) {<br /></span><span style="font-family: courier;"> puts("File open Error");<br /></span><span style="font-family: courier;"> return 1;<br /></span><span style="font-family: courier;"> }</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if ((fpDat=fopen(argv[2],"r"))==NULL) {<br /></span><span style="font-family: courier;"> puts("File open Error");<br /></span><span style="font-family: courier;"> return 1;<br /></span><span style="font-family: courier;"> }</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">// Read P6 PPM format<br /></span><span style="font-family: courier;"> if (fgets(buff,MAXSTR,fpImg)==NULL) {<br /></span><span style="font-family: courier;"> puts("Image file read error");<br /></span><span style="font-family: courier;"> return 1;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (strncmp("P6",buff,2)) {<br /></span><span style="font-family: courier;"> puts("Image file not P6 PPM error");<br /></span><span style="font-family: courier;"> return 1;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> puts("P6");</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> fseek(fpDat,0L, SEEK_END);<br /></span><span style="font-family: courier;"> l = ftell(fpDat);<br /></span><span style="font-family: courier;"> fseek(fpDat,0L, SEEK_SET);<br /></span><span style="font-family: courier;"> printf("#steg Aa A %ld %s\n",l,argv[2]);</span></div><p></p></blockquote><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">// Read width height<br /></span><span style="font-family: courier;"> fscanf(fpImg,"%d %d",&w,&h); //Line 50<br /></span><span style="font-family: courier;"> printf("%d %d\n",w,h);</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">// Read depth<br /></span><span style="font-family: courier;"> fscanf(fpImg,"%s",buff);<br /></span><span style="font-family: courier;"> d=atoi(buff);<br /></span><span style="font-family: courier;"> printf("%d",d);</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (d!=255) {<br /></span><span style="font-family: courier;"> puts("Image depth isn't 255");<br /></span><span style="font-family: courier;"> return 1;<br /></span><span style="font-family: courier;"> }</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (l>(w*h)) {<br /></span><span style="font-family: courier;"> puts("Image size too small!");<br /></span><span style="font-family: courier;"> printf("Image: %ld Data: %ld\n",(long)(w*h),l);<br /></span><span style="font-family: courier;"> return 1;<br /></span><span style="font-family: courier;"> }</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void CleanUp() {<br /></span><span style="font-family: courier;"> if (fpImg!=stdin) fclose(fpImg);<br /></span><span style="font-family: courier;"> if (fpDat!=stdin) fclose(fpDat);<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int ReadData(int argc, char *argv[]) {<br /></span><span style="font-family: courier;"> char bit1,bit2,bit3;<br /></span><span style="font-family: courier;"> char sout;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> long i;<br /></span><span style="font-family: courier;"> long c; char c1;<br /></span><span style="font-family: courier;"> char s1[MAXSTR];<br /></span><span style="font-family: courier;"> char s2[MAXSTR];<br /></span><span style="font-family: courier;"> char s3[MAXSTR];<br /></span><span style="font-family: courier;"> char s4[MAXSTR];<br /></span><span style="font-family: courier;"> char s5[MAXSTR];</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if ((fpImg=fopen(argv[1],"r"))==NULL) {<br /></span><span style="font-family: courier;"> puts("File open Error");<br /></span><span style="font-family: courier;"> return 1;<br /></span><span style="font-family: courier;"> }</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">// Read P6 PPM format<br /></span><span style="font-family: courier;"> if (fgets(buff,MAXSTR,fpImg)==NULL) {<br /></span><span style="font-family: courier;"> puts("Image file read error");<br /></span><span style="font-family: courier;"> return 1;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (strncmp("P6",buff,2)) {<br /></span><span style="font-family: courier;"> puts("Image file not P6 PPM error");<br /></span><span style="font-family: courier;"> return 1;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> fscanf(fpImg,"%s %s %s %s %s",s1,s2,s3,s4,s5);<br /></span><span style="font-family: courier;"> l=atol(s4); strcpy(sname,s5);</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">// Read width height<br /></span><span style="font-family: courier;"> fscanf(fpImg,"%d %d",&w,&h); //Line 50</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">// Read depth<br /></span><span style="font-family: courier;"> fscanf(fpImg,"%d",&d);<br /></span><span style="font-family: courier;"> if (d!=255) {<br /></span><span style="font-family: courier;"> puts("Image depth isn't 255");<br /></span><span style="font-family: courier;"> return 1;<br /></span><span style="font-family: courier;"> }</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> for (i=0;i<l;i++) {<br /></span><span style="font-family: courier;"> bit1=(char) fgetc(fpImg);<br /></span><span style="font-family: courier;"> bit2=(char) fgetc(fpImg);<br /></span><span style="font-family: courier;"> bit3=(char) fgetc(fpImg);<br /></span><span style="font-family: courier;"> sout= ((bit1 & 0x07)<<5)<br /></span><span style="font-family: courier;"> | ((bit2 & 0x03)<<3)<br /></span><span style="font-family: courier;"> | ((bit3 & 0x07));<br /></span><span style="font-family: courier;"> putchar(sout);<br /></span><span style="font-family: courier;"> }</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void ProcessData() {<br /></span><span style="font-family: courier;"> long i,j;<br /></span><span style="font-family: courier;"> int c; char bit;<br /></span><span style="font-family: courier;"> char bit1,bit2,bit3;<br /></span><span style="font-family: courier;"> char sout;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> for (i=0;i<(w*h);i++) {<br /></span><span style="font-family: courier;"> c=fgetc(fpDat);<br /></span><span style="font-family: courier;"> if (c==EOF) {<br /></span><span style="font-family: courier;"> putchar(fgetc(fpImg));<br /></span><span style="font-family: courier;"> putchar(fgetc(fpImg));<br /></span><span style="font-family: courier;"> putchar(fgetc(fpImg));<br /></span><span style="font-family: courier;"> } else {<br /></span><span style="font-family: courier;"> bit=(char) fgetc(fpImg);<br /></span><span style="font-family: courier;"> bit&=0xF8; bit|=(c&0xE0)>>5; bit1=bit;<br /></span><span style="font-family: courier;"> bit=(char) fgetc(fpImg);<br /></span><span style="font-family: courier;"> bit&=0xFC; bit|=(c&0x18)>>3; bit2=bit;<br /></span><span style="font-family: courier;"> bit=(char) fgetc(fpImg);<br /></span><span style="font-family: courier;"> bit&=0xF8; bit|=(c&0x07); bit3=bit;<br /></span><span style="font-family: courier;"> printf("%c%c%c",bit1,bit2,bit3);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int main (int argc, char *argv[] ) {<br /></span><span style="font-family: courier;"> int e=0;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (argc<2) {<br /></span><span style="font-family: courier;"> puts("Write: fileglob [picname.ppm] [datafilename]");<br /></span><span style="font-family: courier;"> puts("Read: fileglob [picname.ppm]");<br /></span><span style="font-family: courier;"> puts("ppm is P6 file (binary)");<br /></span><span style="font-family: courier;"> return 1;<br /></span><span style="font-family: courier;"> }</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (argc==2) ReadData(argc,argv);</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (argc==3) {<br /></span><span style="font-family: courier;"> Init(argc,argv);<br /></span><span style="font-family: courier;"> ProcessData();<br /></span><span style="font-family: courier;"> CleanUp();<br /></span><span style="font-family: courier;"> }</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> return e;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>One more thing:</p><p>Design is much, much harder than coding! In the process of programming this, I changed the design several times. It took me hours to finish this program up to this state, but that's because I keep changing the design. There used to be more parameters required in order to write the image, as well as trying it out directly with PNG format using Processing. But it's not until PPM idea comes into being that the program finally arrived at satisfactory design.</p>Harry Hardjonohttp://www.blogger.com/profile/02635313407341489264noreply@blogger.com0tag:blogger.com,1999:blog-5862124691901496005.post-57249627746788645482022-07-07T04:00:00.006-07:002022-07-07T04:00:00.186-07:00Day 22/100 Fibonacci and Factorial Trailing Zero<h2 style="text-align: left;">Day 22/100 Fibonacci and Factorial Trailing Zero</h2><h3 style="text-align: left;">Failure at Grade School Arithmetic</h3><p><br /></p><p>So, I was at conversation the other day, where the other person was touting the virtues of Python, and dissing C language. You know, the language I'm using to do 100 Days of Code challenge. Truthfully, I did encounter a few "Segmentation Fault" core dump error, but I simply took it in stride. What I didn't know, I soon find out. It's part of the learning process.</p><p><br /></p><p>Why would anybody do it differently? Why would you blame the programming language when you're supposed to increase your own skill so that you no longer make mistakes, instead of expecting the computer to catch yours?</p><p><br /></p><p>If you look at my programs, you'll see my tendency to be light on error checking routines. What can I say? I don't make that many mistakes. Sure I made some. Everybody does. The difference between me and other people is that I learn from my mistakes and not repeat them. I don't see that kind of commitment from your average coder. This is why I wonder if the oft claimed "Coding makes you smarter" is incorrectly attributed to survivor bias.</p><p><br /></p><p>Pardon me for having a dim view of the situation. I have seen too many stupid people who don't know what they're doing, make bold claims that are obviously false. Let's not spread more misinformation than what is already out there.</p><p><br /></p><p>The title above is being honest. The failure does not lie in coding, regardless of platform or programming language chosen. The failure is at grade school level of arithmetic. I'm talking about 5th grader arithmetic here! Add, subtract, multiply, and divide. It doesn't even involve any fraction! How hard can that be?</p><p><br /></p><p>Very hard, it turns out. Let's take a look at fibonacci code I've written. I did it twice: First is my take on it. The second is what is commonly done by the community, assuming neither Dynamic Programming (memoization) nor Recursion is involved. This is LeetCode 509:</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">long long fib1(int n) {<br /></span><span style="font-family: courier;"> int i=1;<br /></span><span style="font-family: courier;"> long long m[2];<br /></span><span style="font-family: courier;"> if (n<1) return 0;<br /></span><span style="font-family: courier;"> if (n>92) return -1; //oob<br /></span><span style="font-family: courier;"> for (m[0]=1,m[1]=1;--n;i=1-i) m[i]+=m[1-i];<br /></span><span style="font-family: courier;"> return m[i];<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">long long fib2(int n) {<br /></span><span style="font-family: courier;"> int i=0; long long a=0;<br /></span><span style="font-family: courier;"> long long b=1;long long c=1;<br /></span><span style="font-family: courier;"> if (n<1) return 0;<br /></span><span style="font-family: courier;"> if (n>92) return -1; //oob<br /></span><span style="font-family: courier;"> for (a=0,b=1,c=1;--n;) {<br /></span><span style="font-family: courier;"> a=b; b=c; c=a+b;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> return b;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>As you can see, my version is more compact than what is usually done. It uses only 2 variables, stored as array, so that I can flip between them. Testing does take a while, but if you pride yourself as a software engineer, then you would want to do it that way! Although mathematicians can resort to recursive solution, software engineer cannot do that! For you to take pride in your coding skill as software engineer, the code has to be extremely tight, and no waste either running time (recursion) or memory (memoization). </p><p><br /></p><p>The second solution is actually acceptable. It's very commonly done by people who aren't mathematically sophisticated. It's kind of like FizzBuzz challenge. Sure, it's easily done, but is it optimum? Not really. So, the second solution is acceptable, but nothing to be proud of.</p><p><br /></p><p>As far as recursion and memoization? In my very strong opinion, those are failures! Waste of cycles and bytes! Very unprofessional! I always say that my code is at amateur hobbyist level, but looking at some of these professional coding, I wonder if I'm not already better than most of them.</p><p><br /></p><p>A second example is even more telling than the fibonacci problem. The problem is to count the number of trailing zeros in factorial. LeetCode 172. Now, we're talking deep into mathematical realm. Sure, leet coder act like it's an easy thing to figure out. But is it? If you can figure out the deep mathematical issues, then surely you can also figure out the most efficient way to compute it? </p><p><br /></p><p>Nope! That's a fail! As far as I'm concerned, this kind of question does not belong in the interview process. Fundamentally, either you ran into the problem already, and remember the solution, or alternatively, you haven't run into it previously, and will now have to compute large samples of factorials to try to determine some kind of patterns that you can recognize. Oh, do you know that in these kind of interviews you cannot use any kind of help including computers and browsers? That's right! You only have the white board to do it.</p><p><br /></p><p>What that tells me is that the company who does these kind of things will fill up their ranks with people who memorize LeetCode problems, instead of the smart coder who can readily research the issue. What's that Einstein, Feynman, et al said? "Do not memorize things that can be looked up?" Exactly!</p><p><br /></p><p>Let's see what the typical answer is involved. You can probably google this in just a few minutes:</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int trail1(int n) {<br /></span><span style="font-family: courier;"> int c; int i;<br /></span><span style="font-family: courier;"> for (c=0,i=5;n/i>=1;i*=5) {<br /></span><span style="font-family: courier;"> c+=(n/i);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> return c;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>Looks nice and easy, doesn't it? But it's deceptively tricky. Can you even work out the problem even after looking at the code? I certainly cannot! I'm no mathematician. I need to see rows of factorials and count the zeros to get some kind of pattern recognition going. This question is not an easy question, despite the brevity of the solution.</p><p><br /></p><p>So, am I a failure? Maybe as a mathematician. However, as a coder? Not only would I pass, those people who give the answer above are all failures! Remember, we're evaluating coding skills, here, not math skills. The only math skill you need is grade school level arithmetic! That's right! No more than arithmetic. Hence the failure is of at grade school level. Now tell me, what kind of highly skilled, highly experienced, highly paid, professional computer programmer would fail grade school math? Only impostors do.</p><p><br /></p><p>You need to have proper foundation in your skills! This goes double if you want to be a professional! No short cuts! If you cannot do grade school arithmetic, I suggest taking up coding as a hobby, rather than being a professional.</p><p><br /></p><p>Here is the proper solution to the question:</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int trail2(int n) {<br /></span><span style="font-family: courier;"> int c=0;<br /></span><span style="font-family: courier;"> for (;n/=5;c+=n);<br /></span><span style="font-family: courier;"> return c;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>One division, and one addition. That's it! </p><p><br /></p><p>Look, coding is hard. I understand that. What I don't understand is why would people fail at grade school arithmetic! The usual solution as shown above features 2 divisions and a multiply. How is that better? It's not better. It's not professional at all!</p><p><br /></p><p>How many years ago did you first learn arithmetic? Are you <b>still</b> at that level? Sigh.</p><p><br /></p><p>Sorry to be so negative about things, but I'm seeing way more incompetence going on lately than what it used to be. Unfortunately, it seems that people just don't care anymore. That's a dangerous attitude to have. In the worst case scenario, it will mean the whole destruction of the industry as we know it. Don't laugh. It happened before. Look up "Dot Com Meltdown" if you don't believe me. That's the equivalent of "Game Industry crash" or even "Great Depression" level of apocalyptic event. Let's not have another one, okay?</p><p><br /></p><p>Sigh.</p><p><br /></p><p>I keep telling people to learn fundamentals, but people just don't bother. They refuse to do so. Why would they? A convenient library is just a download away! Until one day, one of those library disappear and if you google "... brought down the internet", you will find some incredible stories that shouldn't happen, but that they happened!</p><p><br /></p><p>Study your fundamentals!</p><p><br /></p><blockquote style="border: none; margin: 0 0 0 40px; padding: 0px;"><blockquote style="border: none; margin: 0 0 0 40px; padding: 0px;"><p style="text-align: left;"></p><h3 style="text-align: left;">Lookit dem Smileys...</h3><p></p></blockquote></blockquote><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int d8(int B) {<br /></span><span style="font-family: courier;"> int O;<br /></span><span style="font-family: courier;"> return (O= (B /= 5)<br /></span><span style="font-family: courier;"> )? O+ d8 (B ): 0;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>One more thing: Python isn't English! That distinction belongs to Literary Programming as pioneered by Dr. Donald Knuth. Alternatively, you can pull up just about <b>any</b> Design Document. Are you a Rockstar computer programmer?</p><div><br /></div>Harry Hardjonohttp://www.blogger.com/profile/02635313407341489264noreply@blogger.com0tag:blogger.com,1999:blog-5862124691901496005.post-30270103296216953362022-07-06T04:00:00.004-07:002022-07-06T15:00:18.599-07:00Day 21/100 Roman Numeral<h2 style="text-align: left;">Day 21/100 Roman Numeral</h2><h3 style="text-align: left;">MMXX has been a bad year!</h3><p><br /></p><p>I'll just do a quick run today. Basically, I'm intrigued by the possibility of parsing text with text fragments, instead per character or per words. So, I decided to put out an array of text and the converted value. Since this is a quick experiment, and I want to have an actual program, I decided to do Roman numeral conversion. Leet Code 13</p><p><br /></p><p>I don't have to do Roman numeral conversion program. I can do Morse Code, or Phonetic Alphabet, etc. But Roman numeral conversion is simple enough, so why not?</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int roman(char *num) {<br /></span><span style="font-family: courier;"> int i; int n=0; int l;<br /></span><span style="font-family: courier;"> for (i=0;i<strlen(num);i++) num[i]=toupper(num[i]);<br /></span><span style="font-family: courier;"> while (strlen(num)) {<br /></span><span style="font-family: courier;"> for (i=0;i<MAXENTRY;i++) {<br /></span><span style="font-family: courier;"> l=strlen(Romc[i]);<br /></span><span style="font-family: courier;"> if (!strncmp(Romc[i],num,l)) {<br /></span><span style="font-family: courier;"> n+=Romv[i]; num+=l; break;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> return n;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>It took me about an hour to do this, simply because I forgot to Initialize the table! Oh, dear. Can we say C is a terrible language to work with? Not really. I mean, what kind of computer programmer is it, to forget to initialize the table? Also, what kind of computer language can help with that? Syntax error is easy. Semantic error, however, is something you just have to own it.</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">#include <stdio.h><br /></span><span style="font-family: courier;">#include <ctype.h><br /></span><span style="font-family: courier;">#include <string.h></span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">#define MAXDIGIT 5<br /></span><span style="font-family: courier;">#define MAXENTRY 13</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">char Romc[MAXENTRY][MAXDIGIT];<br /></span><span style="font-family: courier;">int Roml[MAXENTRY];<br /></span><span style="font-family: courier;">int Romv[MAXENTRY];</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int roman(char *num) {<br /></span><span style="font-family: courier;"> int i; int n=0; int l;<br /></span><span style="font-family: courier;"> for (i=0;i<strlen(num);i++) num[i]=toupper(num[i]);<br /></span><span style="font-family: courier;"> while (strlen(num)) {<br /></span><span style="font-family: courier;"> for (i=0;i<MAXENTRY;i++) {<br /></span><span style="font-family: courier;"> l=strlen(Romc[i]);<br /></span><span style="font-family: courier;"> if (!strncmp(Romc[i],num,l)) {<br /></span><span style="font-family: courier;"> n+=Romv[i]; num+=l; break;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> return n;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void Init() {<br /></span><span style="font-family: courier;"> strcpy(Romc[0],"CM"); Romv[0]=900;<br /></span><span style="font-family: courier;"> strcpy(Romc[1],"CD"); Romv[1]=400;<br /></span><span style="font-family: courier;"> strcpy(Romc[2],"XC"); Romv[2]=90;<br /></span><span style="font-family: courier;"> strcpy(Romc[3],"XL"); Romv[3]=40;<br /></span><span style="font-family: courier;"> strcpy(Romc[4],"IX"); Romv[4]=9;<br /></span><span style="font-family: courier;"> strcpy(Romc[5],"IV"); Romv[5]=4;<br /></span><span style="font-family: courier;"> strcpy(Romc[6],"M"); Romv[6]=1000;<br /></span><span style="font-family: courier;"> strcpy(Romc[7],"D"); Romv[7]=500;<br /></span><span style="font-family: courier;"> strcpy(Romc[8],"C"); Romv[8]=100;<br /></span><span style="font-family: courier;"> strcpy(Romc[9],"L"); Romv[9]=50;<br /></span><span style="font-family: courier;"> strcpy(Romc[10],"X"); Romv[10]=10;<br /></span><span style="font-family: courier;"> strcpy(Romc[11],"V"); Romv[11]=5;<br /></span><span style="font-family: courier;"> strcpy(Romc[12],"I"); Romv[12]=1;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int main (int argc, char *argv[] ) {<br /></span><span style="font-family: courier;"> int i;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (argc<2) {<br /></span><span style="font-family: courier;"> puts("Usage: roman ROMAN\n");<br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> Init();<br /></span><span style="font-family: courier;"> for (i=1;i<argc;i++) {<br /></span><span style="font-family: courier;"> printf("%6d %s\n",roman(argv[i]),argv[i]);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>One more thing: You probably notice that the logic used here isn't the same as the logic used everywhere else. That's because the goal isn't to convert Roman numerals per se, but as an exercise to parse partial text not separated by words. Those of you who depends on pre-existing libraries, do you even have one? In any language? Sometimes, you just have to buckle down and make your own library. There's no way around it if you want to work on the bleeding edge.</p><p><br /></p>Harry Hardjonohttp://www.blogger.com/profile/02635313407341489264noreply@blogger.com0tag:blogger.com,1999:blog-5862124691901496005.post-20479807023463968492022-07-05T04:00:00.005-07:002022-07-05T04:59:08.441-07:00Day 20/100 Factor<h2 style="text-align: left;">Day 20/100 Factor</h2><h4 style="text-align: left;">Primes and Factors</h4><p><br /></p><p>It's been 20 days so far, and I'm at a point where my momentum has been disrupted. This is because I'm at research stage where things are unknown. This week will probably feature the slowest progress as I am reorganizing my codes. Specifically, I'm doing this to create programs to use. I think that's the difference between my effort and other people's. They learn to code, I'm writing programs to use.</p><p><br /></p><p>It's possible that I will take a week off next week as I am re-orienting myself. I still code everyday, just that I won't be showing off the programs I've written as they are too messy and raw.</p><p><br /></p><p>Take today's program: It's Factor. There's actually a built-in program to do this. Have you seen the source code? It's rather messy! I'm certainly no mathematician. So, I did it the simple way. Even though I'm doing it the simplest way, it does the job quite fast most of the time. The internal program runs at 0.005s, while mine is at 0.027s. That's about 5 times difference, and that's quite normal. In other words, to achieve single digit multiple of performance, there's quite a bit you must do! That's fine by my book. Also remember that I'm not using Gnu C Compiler (GCC). I'm using Tiny C Compiler (TCC) because it compiles so fast.</p><p><br /></p><p>Given all the disadvantages, I'm happy that the program performs at the speed that it is. Of course, if I'm factoring numbers greater than 32 bit, it can bog down quite a bit. Some of the larger numbers, such as those of 64 bit, may even take hours to do. However, the algorithm I use is very simple:</p><p><br /></p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"> printf("F1 %lld: ",n);<br /></span><span style="font-family: courier;"> for (i=1;i<=n;i++) {<br /></span><span style="font-family: courier;"> while ((n%i)==0) {<br /></span><span style="font-family: courier;"> printf("%lld ",i);<br /></span><span style="font-family: courier;"> n/=i; c++;<br /></span><span style="font-family: courier;"> if (i==1) i++;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> printf("\n");<br /></span><span style="font-family: courier;"> if (c==2) return 1;<br /></span><span style="font-family: courier;"> return 0;</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> printf("F2 %lld: 1 ",n);<br /></span><span style="font-family: courier;"> for (i=n/2;n>1 && i>1;i--,c++) {<br /></span><span style="font-family: courier;"> if ((n%i)==0) {<br /></span><span style="font-family: courier;"> printf("%lld ",(n/i));<br /></span><span style="font-family: courier;"> n=i;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> printf("%lld\n",n);<br /></span><span style="font-family: courier;"> return (n/i);</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>As you can see, there are 2 versions of code. Both returns a condition if the number is prime, so you can check the number for prime. Like so:</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (factor1(n)) puts("Prime");<br /></span><span style="font-family: courier;"> if (n==factor2(n)) puts("Prime");</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>And that makes all the difference. Trying to give that is what makes the code so challenging to write, especially since I'm approaching the problem from both direction: Increasing and Decreasing.</p><p><br /></p><p>Most people, when given a problem, will solve it one way, but never bothered to solve it again another way. That's no way to learn! Always do it more than once. In fact, I habitually do it at least 3 times: The good way, the better way, and the best way. Adopting that philosophy yields the most efficient result in regard to cost/performance gain, and so I would encourage you to do it that way, too.</p><p><br /></p><p>At the very least, try to approach the problem from opposite point of view. If you look left, look right! If you look up, look down! If you look forward, look backward! It's that easy! There's nothing stopping you from doing it, except yourself. </p><p><br /></p><p>The LeetCode challenge 254 expects you to output combinations as well, but when's the last time that kind of algorithm was used? Nothing that I can think of. Anyway, here is the completed factor program:</p><div style="text-align: left;"><blockquote> <br /><span style="font-family: courier;">#include <stdio.h><br /></span><span style="font-family: courier;">#include <stdlib.h></span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int factor1(long long n) {<br /></span><span style="font-family: courier;"> long long i;<br /></span><span style="font-family: courier;"> long long c=0;</span></blockquote><span style="font-family: courier;"></span></div><div><span style="font-family: courier;"></span></div><blockquote><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;"> printf("F1 %lld: ",n);</span></div><div><span style="font-family: courier;"> for (i=1;i<=n;i++) {</span></div><div><span style="font-family: courier;"> while ((n%i)==0) {</span></div><div><span style="font-family: courier;"> printf("%lld ",i);</span></div><div><span style="font-family: courier;"> n/=i; c++;</span></div><div><span style="font-family: courier;"> if (i==1) i++;</span></div><div><span style="font-family: courier;"> }</span></div><div><span style="font-family: courier;"> }</span></div><div><span style="font-family: courier;"> printf("\n");</span></div><div><span style="font-family: courier;"> if (c==2) return 1;</span></div><div><span style="font-family: courier;"> return 0;</span></div><div><span style="font-family: courier;">}</span></div></blockquote><div><span style="font-family: courier;"></span></div><div><br /></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int factor2(long long n) {<br /></span><span style="font-family: courier;"> long long i; long long c=0;<br /></span><span style="font-family: courier;"> printf("F2 %lld: 1 ",n);<br /></span><span style="font-family: courier;"> for (i=n/2;n>1 && i>1;i--,c++) {<br /></span><span style="font-family: courier;"> if ((n%i)==0) {<br /></span><span style="font-family: courier;"> printf("%lld ",(n/i));<br /></span><span style="font-family: courier;"> n=i;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> printf("%lld\n",n);<br /></span><span style="font-family: courier;"> return (n/i);<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int main (int argc, char *argv[]) {<br /></span><span style="font-family: courier;"> int i,n;<br /></span><span style="font-family: courier;"> if (argc<2) { puts("factor [NUMBER] ..."); return 0; }</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> for (i=1;i<argc;i++) {<br /></span><span style="font-family: courier;"> n=atoll(argv[i]);<br /></span><span style="font-family: courier;"> if (factor1(n)) puts("Prime");<br /></span><span style="font-family: courier;"> if (n==factor2(n)) puts("Prime");<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>One more thing: In this case, I did another try another factoring algorithm involving recursion, but that didn't pan out, it being a fragile algorithm, so I didn't bother to show you. But it does take a few hours of my time as I try the algorithm, just so you know.</p><div><br /></div>Harry Hardjonohttp://www.blogger.com/profile/02635313407341489264noreply@blogger.com0tag:blogger.com,1999:blog-5862124691901496005.post-47053544130357806362022-07-04T04:00:00.003-07:002022-07-04T04:00:00.189-07:00Day 19/100 FizzBuzz<h2 style="text-align: left;">Day 19/100 FizzBuzz</h2><h3 style="text-align: left;">FizzBuzz Buzzineezz</h3><p><br /></p><p>Yeah, you know it's going to happen eventually. I Fizz the FizzBuzz Buzz. Lame, I know. But here it is...</p><p><br /></p><p>FizzBuzz program basically prints out numbers from 1 to 100, except that if the number is evenly divisible by 3, it prints "Fizz" instead. If the number is evenly divisible by 5, it prints "Buzz" instead. And if the number is evenly divisible by 3 and 5, it prints "FizzBuzz" instead. This is LeetCode 412.</p><p><br /></p><p>So, here is the first solution that comes to mind. This isn't a unique solution, by any means, just the one most readily comes to mind.</p><p><br /></p><h3 style="text-align: left;">FB1</h3><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;">void FizzBuzz1() {<br /></span><span style="font-family: courier;"> int i;<br /></span><span style="font-family: courier;"> for (i=1;i<=100;i++) {<br /></span><span style="font-family: courier;"> if (!(i%3) && !(i%5)) printf("FizzBuzz\n");<br /></span><span style="font-family: courier;"> else if (!(i%3)) printf("Fizz\n");<br /></span><span style="font-family: courier;"> else if (!(i%5)) printf("Buzz\n");<br /></span><span style="font-family: courier;"> else printf("%d\n",i);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p><br /></p><p>The problem here is that the solution isn't exactly clever. It works, but that's about it. Another thing to worry about is that the program isn't really easily extended. How about if you want to add "Bazz" for numbers evenly divisible by 7? And add "Bang" for numbers evenly divisible by 9? You can see that hard coding the solution like that doesn't bring any prestige point to the programmer. As a side note, failing at the task will certainly bring shame to the programmer.</p><p><br /></p><p>So, let's improve the solution. Thinking about it, the problem is that it has different states to the solution. Especially important is that you don't want to show the number if the answer is "Fizz", "Buzz", or both! That's a failure point, so be careful!</p><p><br /></p><p>The standard professional engineering way to solve this is via states. Something like this:</p><p><br /></p><h3 style="text-align: left;">FB2</h3><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;">void FizzBuzz2() {<br /></span><span style="font-family: courier;"> int i;<br /></span><span style="font-family: courier;"> int s=0;<br /></span><span style="font-family: courier;"> for (s=0,i=1;i<=100;s=0,i++) {<br /></span><span style="font-family: courier;"> if (!(i%3)) s+=1;<br /></span><span style="font-family: courier;"> if (!(i%5)) s+=2;<br /></span><span style="font-family: courier;"> switch (s) {<br /></span><span style="font-family: courier;"> case 0: printf("%d\n",i); break;<br /></span><span style="font-family: courier;"> case 1: printf("Fizz\n"); break;<br /></span><span style="font-family: courier;"> case 2: printf("Buzz\n"); break;<br /></span><span style="font-family: courier;"> case 3: printf("FizzBuzz\n"); break;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>And that works. But it's somewhat big, over engineered program, isn't it? In fact, that is the professsional way to do things. I guess now you know why I'm firmly at the side of amateur hobbyist side. I no longer have any patience in overbearing bureaucratic structures. Well, if the program needs it, I don't mind. Usually, they don't need it, though. Let's simplify that monstrosity.</p><p><br /></p><h3 style="text-align: left;">FB3</h3><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;">void FizzBuzz3() {<br /></span><span style="font-family: courier;"> int i;<br /></span><span style="font-family: courier;"> int s=0;<br /></span><span style="font-family: courier;"> for (i=1;i<=100;i++) {<br /></span><span style="font-family: courier;"> s=0;<br /></span><span style="font-family: courier;"> if (!(i%3)) { s=1; printf("Fizz"); }<br /></span><span style="font-family: courier;"> if (!(i%5)) { s=1; printf("Buzz"); }<br /></span><span style="font-family: courier;"> if (!s) { printf("%d",i); }<br /></span><span style="font-family: courier;"> printf("\n");<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>So, in fact, we only need one state. Are we printing number? Or not? We don't need to get fancy! And that's a good solution, too, albeit less structured, and perhaps a little bit more difficult to read. Let's compact the program even more!</p><p><br /></p><h3 style="text-align: left;">FB4</h3><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;">void FizzBuzz4() {<br /></span><span style="font-family: courier;"> int i;<br /></span><span style="font-family: courier;"> for (i=1;i<=100;i++) {<br /></span><span style="font-family: courier;"> printf("%d\r%s%s\n",i,<br /></span><span style="font-family: courier;"> (i%3)?"":"Fizz",<br /></span><span style="font-family: courier;"> (i%5)?"":"Buzz");<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>It does look like it works and it's only one line, but there's a trick to it. The output depends on the fact that it uses '\r' carriage return character, which means that the number is always displayed, but hidden when FizzBuzz occur. Visually, it's the same thing, but if you check the output via program such as diff, then it will fail. Still, that's a neat hack that you can do to impress people!</p><p><br /></p><h3 style="text-align: left;">FB5</h3><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;">void FizzBuzz5() {<br /></span><span style="font-family: courier;"> int i=0;<br /></span><span style="font-family: courier;"> while(100>i++){switch(p("%s%s",(i<br /></span><span style="font-family: courier;"> %3)?"":"Fizz",(i%5)?"":"Buzz")) {<br /></span><span style="font-family: courier;"> case 0:p("%d",i);default:p("\n");<br /></span><span style="font-family: courier;">}}}</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><h3 style="text-align: left;">FB6</h3><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;">void FizzBuzz6() {<br /></span><span style="font-family: courier;"> for(int i=0;100>i++;)<br /></span><span style="font-family: courier;"> switch(p("%s%s",(i%3)<br /></span><span style="font-family: courier;"> ?"": "Fizz",(i%5)?"":<br /></span><span style="font-family: courier;"> "Buzz")){case 0:p("%d"<br /></span><span style="font-family: courier;"> ,i);default :p("\n");<br /></span><span style="font-family: courier;">}}</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>Then again, there is impressive, and just plain old ridiculous! There's only a fine line between the two.</p><p><br /></p><p>One more thing: If you're wondering what's p(), it's printf(). I simply define it in the beginning of the program.</p><p><br /></p>Harry Hardjonohttp://www.blogger.com/profile/02635313407341489264noreply@blogger.com0tag:blogger.com,1999:blog-5862124691901496005.post-29042431777221697062022-07-03T04:00:00.004-07:002022-07-03T04:00:00.168-07:00Day 18/100 Turtle2 (Improved)<h2 style="text-align: left;"> Day 18/100 Turtle 2 (Improved)</h2><h3 style="text-align: left;">Do turtles come in red?</h3><p><br /></p><p>If you remember Day 14, I did a simple turtle graphic program. Well, I revisited the program, and add a bunch of features. A little too much, maybe. It has over 300 lines on it. Quite a program. Yet, it is not complete yet. There's still quite a few capabilities I want to put it in, but it suffices for now.</p><p><br /></p><p>The code is interesting because of the function Turtle() actually acts like an object. Structurally, it has 4 parameters: 2 strings and 2 numbers. The first string is actually a command for the turtle. Object methods, so to speak. The rest are the parameters, except it's not object oriented. This is just plain old C, instead of C++.</p><p><br /></p><p>If I want to, I can do it as a graphic library, and I still have an option to do that. Just do it as an abstraction layer, or something. But it's getting complicated, and I'm thinking maybe I should stop here for now, and build some kind of documentation. As it is, it's good enough for some fancy graphic:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUXvDkAREfX-e4EV2BPbfejzl17is9N7NXIYcw05GJV0pstTiqEiR2b8IWEHBxSBY42eN3q1W-fUUZFB22pLXmP-BpqkQnHIafHBz8v6mK31iwgba9zLlDYgl-8gWQs7GmoWKKVP9_K0dfY8S35ffycqGg0UL1oH7voMM71Gs67iIE0bW14B2ZxO1g/s673/spark.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="673" data-original-width="454" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUXvDkAREfX-e4EV2BPbfejzl17is9N7NXIYcw05GJV0pstTiqEiR2b8IWEHBxSBY42eN3q1W-fUUZFB22pLXmP-BpqkQnHIafHBz8v6mK31iwgba9zLlDYgl-8gWQs7GmoWKKVP9_K0dfY8S35ffycqGg0UL1oH7voMM71Gs67iIE0bW14B2ZxO1g/s320/spark.png" width="216" /></a></div><br /><p><br /></p><p style="text-align: center;">A picture of a random tree</p><p><br /></p><p>Most commands comes in pairs. Usually the point is obvious if you look at the code. The function Turtle() is rather large, but if you look at individual commands, it's actually rather simple for each. Something to remember that doing graphic is usually a library call away. Well, not this one. Here, I simply put out SVG commands, and that's a simple text output.</p><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> //TreeMaker with Spark?</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (r>30) {<br /></span><span style="font-family: courier;"> for (i=3+(rand()%n);i;i--) {<br /></span><span style="font-family: courier;"> x1=x0+(rand()%r-(r/2));<br /></span><span style="font-family: courier;"> y1=y0+(rand()%r-(r/3));<br /></span><span style="font-family: courier;"> Turtle("G","",x0,y0);<br /></span><span style="font-family: courier;"> Turtle("C","",0x102030,0);<br /></span><span style="font-family: courier;"> Turtle("G","",x1,y1);<br /></span><span style="font-family: courier;"> Spark1(x1,y1,n/2,r/2);<br /></span><span style="font-family: courier;"> }}</span></div><p style="text-align: left;"></p></blockquote><p style="text-align: left;"><br /></p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> Turtle("SC","",0,0);<br /></span><span style="font-family: courier;"> srand(3333);Turtle("C","",0x010101,0);<br /></span><span style="font-family: courier;"> Turtle("G","",60,20);Spark1(60,90,32,75);<br /></span><span style="font-family: courier;"> srand(6666);Turtle("C","",0,0);<br /></span><span style="font-family: courier;"> Turtle("G","",60,20);Spark1(60,90,32,70);<br /></span><span style="font-family: courier;"> srand(9999);Turtle("C","",0,0);<br /></span><span style="font-family: courier;"> Turtle("G","",60,20);Spark1(60,90,32,60);<br /></span><span style="font-family: courier;"> srand(18100);Turtle("C","",0,0);<br /></span><span style="font-family: courier;"> Turtle("G","",60,20);Spark2(60,90,32,60);<br /></span><span style="font-family: courier;"> Turtle("sc","",0,0);</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>This is the main code for drawing the tree. It uses 2 Spark functions. Originally, I used a recursive function, but then I added color, and well, there you go. I'd say the tree looks good enough for something that is random.</p><p><br /></p><p>I also added some SVG capabilities, such as Fonts. I'm thinking that maybe I should just change the name from Turtle to SVG Library. Oh, well, that is something to do in the future. I may as well do it, too. It's no longer a turtle graphic program when I eliminate turn left and turn right. Those has been replaced with Heading(relative) and Heading(absolute). </p><p><br /></p><p>Furthermore, I changed the program so that it can handle multiple character command. So, with that, it has greatly expanded the capability of taking in numerous commands. BTW, most commands comes in upper case and lower case versions.</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">SC: prints out SVG file header<br /></span><span style="font-family: courier;">sc: prints out SVG file footer</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;">F - n1: Forward, absolute distance<br /></span><span style="font-family: courier;">f - n1: forward, relative distance</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;">G - n1,n2: Goto XY, absolute<br /></span><span style="font-family: courier;">g - n1,n2: Goto XY, relative</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;">H - n1: Heading, absolute (0-360)<br /></span><span style="font-family: courier;">h - n1: Heading, relative</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;">C - n1: Stroke (pen) color. 0 for pen up<br /></span><span style="font-family: courier;">c - n1: Fill color. 0 for "none"</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;">T - s2,n1: Set Font, Font name, size<br /></span><span style="font-family: courier;">t - s2,n1,n2: Draw Text. Text,X,Y</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;">M1 - EvenOdd Fill mode. Uses background color<br /></span><span style="font-family: courier;">m1 - disable fill mode.</span></blockquote><span style="font-family: courier;"></span></div><p style="text-align: left;"><br /></p><p style="text-align: left;">These command set is enough to allow for some sophisticated graphic. I was even able to include the SVG code in my blog! So, that's good.</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">#include <stdio.h><br /></span><span style="font-family: courier;">#include <stdlib.h><br /></span><span style="font-family: courier;">#include <string.h><br /></span><span style="font-family: courier;">#include <math.h><br /></span><span style="font-family: courier;">#include <stdlib.h></span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;">#define MAXENTRY 10000<br /></span><span style="font-family: courier;">#define MAXSTR 2560<br /></span><span style="font-family: courier;">#define sx0 0<br /></span><span style="font-family: courier;">#define sx1 118<br /></span><span style="font-family: courier;">#define sy0 0<br /></span><span style="font-family: courier;">#define sy1 180</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;">#define PI 3.141528</span></div><p style="text-align: left;"></p></blockquote><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">char Liner[MAXSTR];<br /></span><span style="font-family: courier;">char Data[MAXENTRY][MAXSTR];<br /></span><span style="font-family: courier;">int numentry;<br /></span><span style="font-family: courier;">int Debug=0;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">//turtle<br /></span><span style="font-family: courier;">char co; //command<br /></span><span style="font-family: courier;">int nu; //Number<br /></span><span style="font-family: courier;">int he; //heading<br /></span><span style="font-family: courier;">int di; //distance<br /></span><span style="font-family: courier;">float an; //angle (rad)<br /></span><span style="font-family: courier;">float tx0,ty0,tx1,ty1; //line<br /></span><span style="font-family: courier;">int pe; //pen color<br /></span><span style="font-family: courier;">int bg; //background color<br /></span><span style="font-family: courier;">int mode=0; //0-normal 1-fill<br /></span><span style="font-family: courier;">char FontFam[MAXSTR];<br /></span><span style="font-family: courier;">int FontSiz;</span></blockquote><p></p></div><blockquote><div style="text-align: left;"><p> </p><span style="font-family: courier;"></span></div><p><span style="font-family: courier;">float map(float x0,float x1, float x2,float y0, float y2) {</span></p><p><span style="font-family: courier;"> return y0+((x1-x0)*(y2-y0)/(x2-x0)); //y1</span></p><p><span style="font-family: courier;">}</span></p></blockquote><p><span style="font-family: courier;"></span></p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void SVGHeader() {<br /></span><span style="font-family: courier;"> puts("<svg xmlns:xlink=\"http://www.w3.org/1999/xlink\" <br /></span><span style="font-family: courier;">style=\"fill-opacity:1; color-rendering:auto; <br /></span><span style="font-family: courier;">color-interpolation:auto; text-rendering:auto; <br /></span><span style="font-family: courier;">stroke:black; stroke-linecap:square; <br /></span><span style="font-family: courier;">stroke-miterlimit:10; shape-rendering:auto; <br /></span><span style="font-family: courier;">stroke-opacity:0.4; fill:black; <br /></span><span style="font-family: courier;">stroke-dasharray:none; font-weight:normal; <br /></span><span style="font-family: courier;">stroke-width:0.25; font-family:'Dialog'; font-style:normal; <br /></span><span style="font-family: courier;">stroke-linejoin:miter; font-size:12px; <br /></span><span style="font-family: courier;">stroke-dashoffset:0; image-rendering:auto;\" </span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">width=\"128.0mm\" height=\"190.0mm\" <br /></span><span style="font-family: courier;">viewBox=\"0 0 128.0 190.0\" </span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">xmlns=\"http://www.w3.org/2000/svg\"><br /></span><span style="font-family: courier;"><!--Template generated by the Batik Graphics2D SVG Generator--><br /></span><span style="font-family: courier;"><defs id=\"genericDefs\" /></span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;"><g><br /></span><span style="font-family: courier;"><line x1=\"10.0\" y1=\"10.0\" x2=\"118.0\" y2=\"10.0\" /><br /></span><span style="font-family: courier;"><line x1=\"118.0\" y1=\"10.0\" x2=\"118.0\" y2=\"180.0\" /><br /></span><span style="font-family: courier;"><line x1=\"10.0\" y1=\"180.0\" x2=\"118.0\" y2=\"180.0\" /><br /></span><span style="font-family: courier;"><line x1=\"10.0\" y1=\"180.0\" x2=\"10.0\" y2=\"10.0\" /></span><span style="font-family: courier;"><br /></span><span style="font-family: courier;">");<br /></span><span style="font-family: courier;">}</span></div><p style="text-align: left;"></p></blockquote><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void SVGFooter() {<br /></span><span style="font-family: courier;"> puts("<br /></span><span style="font-family: courier;"></g><br /></span><span style="font-family: courier;"></svg></span><span style="font-family: courier;"><br /></span><span style="font-family: courier;">");<br /></span><span style="font-family: courier;">}</span></div><p style="text-align: left;"></p></blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void SVGDrawLine(float x0,float y0,float x1,float y1) {<br /></span><span style="font-family: courier;"> int t;</span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (mode==1) {<br /></span><span style="font-family: courier;"> if (pe) {<br /></span><span style="font-family: courier;"> printf("L %f,%f ",x1,y1);<br /></span><span style="font-family: courier;"> } else {<br /></span><span style="font-family: courier;"> printf("M %f,%f ",x1,y1);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> } else if (pe) {<br /></span><span style="font-family: courier;"> printf("<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" />\n",<br /></span><span style="font-family: courier;"> x0,y0,x1,y1);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int Turtle(char s1[], char s2[], int n1, int n2) {</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (!strncmp("SC",s1,2)) { //Capture SVG<br /></span><span style="font-family: courier;"> SVGHeader();<br /></span><span style="font-family: courier;"> if (Debug) puts("SVGStart");<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("sc",s1,2)) { //Close SVG<br /></span><span style="font-family: courier;"> SVGFooter();<br /></span><span style="font-family: courier;"> if (Debug) puts("SVGEnd");<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("F",s1,1)) { //forward absolute<br /></span><span style="font-family: courier;"> di=n1;<br /></span><span style="font-family: courier;"> if (Debug) printf("Forward Absolute %d\n",di);<br /></span><span style="font-family: courier;"> an=map(0.0,(float)he,360.0,0,2*PI);<br /></span><span style="font-family: courier;"> tx1=tx0+(float)di*sin(an);<br /></span><span style="font-family: courier;"> ty1=ty0-(float)di*cos(an);<br /></span><span style="font-family: courier;"> SVGDrawLine(tx0,ty0,tx1,ty1);<br /></span><span style="font-family: courier;"> tx0=tx1;ty0=ty1;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("f",s1,1)) { //forward relative<br /></span><span style="font-family: courier;"> di+=n1;<br /></span><span style="font-family: courier;"> if (Debug) printf("Forward Relative %d\n",di);<br /></span><span style="font-family: courier;"> an=map(0.0,(float)he,360.0,0,2*PI);<br /></span><span style="font-family: courier;"> tx1=tx0+(float)di*sin(an);<br /></span><span style="font-family: courier;"> ty1=ty0-(float)di*cos(an);<br /></span><span style="font-family: courier;"> SVGDrawLine(tx0,ty0,tx1,ty1);<br /></span><span style="font-family: courier;"> tx0=tx1;ty0=ty1;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("G",s1,1)) { //Goto XY Absolute<br /></span><span style="font-family: courier;"> tx1=n1; ty1=n2;<br /></span><span style="font-family: courier;"> SVGDrawLine(tx0,ty0,tx1,ty1);<br /></span><span style="font-family: courier;"> tx0=tx1;ty0=ty1;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("g",s1,1)) { //Goto XY Relative<br /></span><span style="font-family: courier;"> tx1=tx0+n1; ty1=ty0+n2;<br /></span><span style="font-family: courier;"> SVGDrawLine(tx0,ty0,tx1,ty1);<br /></span><span style="font-family: courier;"> tx0=tx1;ty0=ty1;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("H",s1,1)) { //Heading Absolute<br /></span><span style="font-family: courier;"> he=n1;<br /></span><span style="font-family: courier;"> if (Debug) printf("Heading Absolute %d\n",he);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("h",s1,1)) { //Heading Relative<br /></span><span style="font-family: courier;"> he+=n1;<br /></span><span style="font-family: courier;"> if (Debug) printf("Heading Relative %d\n",he);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("C",s1,1)) { //Color Stroke<br /></span><span style="font-family: courier;"> pe=n1;<br /></span><span style="font-family: courier;"> if (Debug) printf("Pen color %d\n",pe);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("c",s1,1)) { //Color Fill<br /></span><span style="font-family: courier;"> bg=n1;<br /></span><span style="font-family: courier;"> if (Debug) printf("Background color %d\n",pe);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("T",s1,1)) { //Font Fam+Siz<br /></span><span style="font-family: courier;"> strcpy(FontFam,s2);<br /></span><span style="font-family: courier;"> FontSiz=n1;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("t",s1,1)) { //Draw text<br /></span><span style="font-family: courier;"> printf("<text x=\"%d\" y=\"%d\" font-family=\"%s\" font-size=\"%d%%\" >"<br /></span><span style="font-family: courier;"> ,n1,n2,FontFam,FontSiz);<br /></span><span style="font-family: courier;"> printf("%s",s2);<br /></span><span style="font-family: courier;"> printf("</text>\n");<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("M1",s1,2)) { //Mode 1 start<br /></span><span style="font-family: courier;"> mode=1;<br /></span><span style="font-family: courier;"> if (bg) {<br /></span><span style="font-family: courier;"> printf("<path stroke=\"#%6X\" fill-rule=\"evenodd\" fill=\"#%6X\" d=\"\n"<br /></span><span style="font-family: courier;"> ,pe,bg);<br /></span><span style="font-family: courier;"> } else {<br /></span><span style="font-family: courier;"> printf("<path stroke=\"#%6X\" fill-rule=\"evenodd\" fill=\"none\" d=\"\n"<br /></span><span style="font-family: courier;"> ,pe,bg);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> printf("M %f,%f ",tx0,ty0);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("m1",s1,2)) { //Mode 1 end<br /></span><span style="font-family: courier;"> mode=0;<br /></span><span style="font-family: courier;"> puts("\" />");<br /></span><span style="font-family: courier;"> }</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></div><p style="text-align: left;"></p></blockquote><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int Init() {<br /></span><span style="font-family: courier;"> co=' ';<br /></span><span style="font-family: courier;"> nu=0; //Number<br /></span><span style="font-family: courier;"> he=0; //heading<br /></span><span style="font-family: courier;"> di=0; //distance<br /></span><span style="font-family: courier;"> an=0; //angle (deg)<br /></span><span style="font-family: courier;"> tx0=59;ty0=90; //line from<br /></span><span style="font-family: courier;"> tx1=tx0;ty1=ty0; //line to<br /></span><span style="font-family: courier;"> pe=1; //pen<br /></span><span style="font-family: courier;"> strcpy(FontFam,"PibotoThin");<br /></span><span style="font-family: courier;"> FontSiz=10;<br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int ProcessData() {<br /></span><span style="font-family: courier;"> char Command[MAXSTR];<br /></span><span style="font-family: courier;"> char Value[MAXSTR];<br /></span><span style="font-family: courier;"> int Num1=0;<br /></span><span style="font-family: courier;"> int Num2=0;</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> int i,j;</span></div><p style="text-align: left;"></p></blockquote><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> Turtle("C","",0x112233,0);<br /></span><span style="font-family: courier;"> Turtle("c","",0xCCBBAA,0);<br /></span><span style="font-family: courier;"> Turtle("SC","",0,0);<br /></span><span style="font-family: courier;">// Turtle("M1","",0,0);<br /></span><span style="font-family: courier;"> for (i=10;i<170;i+=5) {<br /></span><span style="font-family: courier;"> Turtle("C","",0,0);<br /></span><span style="font-family: courier;"> Turtle("G","",10,i);<br /></span><span style="font-family: courier;"> Turtle("C","",0x102030,0);<br /></span><span style="font-family: courier;"> Turtle("G","",113,i);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;">// Turtle("m1","",0,0);<br /></span><span style="font-family: courier;"> Turtle("T","FreeMono",40,0);<br /></span><span style="font-family: courier;"> Turtle("t","FreeMono 40",15,20);<br /></span><span style="font-family: courier;"> Turtle("t","ABCDEFGHIKLMNOPQRSTUVWXYZ",15,25);<br /></span><span style="font-family: courier;"> Turtle("t","abcdefghijklmnopqrstuvwxyz",15,30);<br /></span><span style="font-family: courier;"> Turtle("T","FreeSans",40,0);<br /></span><span style="font-family: courier;"> Turtle("t","FreeSans 40",15,35);<br /></span><span style="font-family: courier;"> Turtle("t","ABCDEFGHIKLMNOPQRSTUVWXYZ",15,40);<br /></span><span style="font-family: courier;"> Turtle("t","abcdefghijklmnopqrstuvwxyz",15,45);<br /></span><span style="font-family: courier;"> Turtle("T","FreeSerif",40,0);<br /></span><span style="font-family: courier;"> Turtle("t","FreeSerif 40",15,50);<br /></span><span style="font-family: courier;"> Turtle("t","ABCDEFGHIKLMNOPQRSTUVWXYZ",15,55);<br /></span><span style="font-family: courier;"> Turtle("t","abcdefghijklmnopqrstuvwxyz",15,60);</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> Turtle("T","Quicksand Light",50,0);<br /></span><span style="font-family: courier;"> Turtle("t","Quicksand Light 50",15,70);<br /></span><span style="font-family: courier;"> Turtle("t","The quick brown fox jumps over the",15,75);<br /></span><span style="font-family: courier;"> Turtle("t","ABCDEFGHIKLMNOPQRSTUVWXYZ",15,80);<br /></span><span style="font-family: courier;"> Turtle("t","abcdefghijklmnopqrstuvwxyz",15,85);</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> Turtle("T","Quicksand Light",40,0);<br /></span><span style="font-family: courier;"> Turtle("t","Quicksand Light 40",15,95);<br /></span><span style="font-family: courier;"> Turtle("t","The quick brown fox jumps over the lazy dog",15,100);<br /></span><span style="font-family: courier;"> Turtle("t","ABCDEFGHIKLMNOPQRSTUVWXYZ",15,105);<br /></span><span style="font-family: courier;"> Turtle("t","abcdefghijklmnopqrstuvwxyz",15,110);</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> Turtle("T","Quicksand Light",30,0);<br /></span><span style="font-family: courier;"> Turtle("t","Quicksand Light 30",15,120);<br /></span><span style="font-family: courier;"> Turtle("t","The quick brown fox jumps over the lazy dog",15,125);<br /></span><span style="font-family: courier;"> Turtle("t","ABCDEFGHIKLMNOPQRSTUVWXYZ",15,130);<br /></span><span style="font-family: courier;"> Turtle("t","abcdefghijklmnopqrstuvwxyz",15,135);</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> Turtle("T","Quicksand Light",20,0);<br /></span><span style="font-family: courier;"> Turtle("t","Quicksand Light 20",15,145);<br /></span><span style="font-family: courier;"> Turtle("t","The quick brown fox jumps over the lazy dog",15,150);<br /></span><span style="font-family: courier;"> Turtle("t","ABCDEFGHIKLMNOPQRSTUVWXYZ",15,155);<br /></span><span style="font-family: courier;"> Turtle("t","abcdefghijklmnopqrstuvwxyz",15,160);</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> Turtle("sc","",0,0);<br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int Spark1(int x0,int y0, int n, int r) {<br /></span><span style="font-family: courier;"> int i;<br /></span><span style="font-family: courier;"> int x1,y1;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (r>30) {<br /></span><span style="font-family: courier;"> for (i=3+(rand()%n);i;i--) {<br /></span><span style="font-family: courier;"> x1=x0+(rand()%r-(r/2));<br /></span><span style="font-family: courier;"> y1=y0+(rand()%r-(r/3));<br /></span><span style="font-family: courier;"> Turtle("G","",x0,y0);<br /></span><span style="font-family: courier;"> Turtle("C","",0x102030,0);<br /></span><span style="font-family: courier;"> Turtle("G","",x1,y1);<br /></span><span style="font-family: courier;"> Spark1(x1,y1,n/2,r/2);<br /></span><span style="font-family: courier;"> }}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (r<=30) {<br /></span><span style="font-family: courier;"> Turtle("c","",0x99FF99,0);<br /></span><span style="font-family: courier;"> Turtle("M1","",0,0);<br /></span><span style="font-family: courier;"> for (i=3+(rand()%n);i;i--) {<br /></span><span style="font-family: courier;"> x1=x0+(rand()%r-(r/4));<br /></span><span style="font-family: courier;"> y1=y0+(rand()%r-(r/3));<br /></span><span style="font-family: courier;"> Turtle("G","",x1,y1);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> Turtle("m1","",0,0);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></blockquote><p></p></div><blockquote><div style="text-align: left;"><p> </p><span style="font-family: courier;"></span></div><p><span style="font-family: courier;">int Spark2(int x0,int y0, int n, int r) {</span></p><p><span style="font-family: courier;"> int i;</span></p><p><span style="font-family: courier;"> int x1,y1;</span></p><p></p></blockquote><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (r>15) {<br /></span><span style="font-family: courier;"> for (i=3+(rand()%n);i;i--) {<br /></span><span style="font-family: courier;"> x1=x0+(rand()%r-(r/2));<br /></span><span style="font-family: courier;"> y1=y0+(rand()%r-(r/3));<br /></span><span style="font-family: courier;"> Turtle("G","",x0,y0);<br /></span><span style="font-family: courier;"> Turtle("C","",0x102030,0);<br /></span><span style="font-family: courier;"> Turtle("G","",x1,y1);<br /></span><span style="font-family: courier;"> Spark2(x1,y1,n/2,r/2);<br /></span><span style="font-family: courier;"> }}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (r<=15) {<br /></span><span style="font-family: courier;"> Turtle("c","",0x338833,0);<br /></span><span style="font-family: courier;"> Turtle("M1","",0,0);<br /></span><span style="font-family: courier;"> for (i=3+(rand()%n);i;i--) {<br /></span><span style="font-family: courier;"> x1=x0+(rand()%r-(r/4));<br /></span><span style="font-family: courier;"> y1=y0+(rand()%r-(r/3));<br /></span><span style="font-family: courier;"> Turtle("G","",x1,y1);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> Turtle("m1","",0,0);<br /></span><span style="font-family: courier;"> }</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></div><p style="text-align: left;"></p></blockquote><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int main (int argc, char *argv[] ) {<br /></span><span style="font-family: courier;"> int n,i;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> Init();<br /></span><span style="font-family: courier;">// ProcessData();</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> //TreeMaker with Spark?<br /></span><span style="font-family: courier;"> Turtle("SC","",0,0);<br /></span><span style="font-family: courier;"> srand(3333);Turtle("C","",0x010101,0);<br /></span><span style="font-family: courier;"> Turtle("G","",60,20);Spark1(60,90,32,75);<br /></span><span style="font-family: courier;"> srand(6666);Turtle("C","",0,0);<br /></span><span style="font-family: courier;"> Turtle("G","",60,20);Spark1(60,90,32,70);<br /></span><span style="font-family: courier;"> srand(9999);Turtle("C","",0,0);<br /></span><span style="font-family: courier;"> Turtle("G","",60,20);Spark1(60,90,32,60);<br /></span><span style="font-family: courier;"> srand(18100);Turtle("C","",0,0);<br /></span><span style="font-family: courier;"> Turtle("G","",60,20);Spark2(60,90,32,60);<br /></span><span style="font-family: courier;"> Turtle("sc","",0,0);</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></div><p style="text-align: left;"></p></blockquote><p style="text-align: left;"><br /></p><p style="text-align: left;">One more thing: Should I actually just make this an SVG library with Turtle layer?</p><div><br /></div>Harry Hardjonohttp://www.blogger.com/profile/02635313407341489264noreply@blogger.com0tag:blogger.com,1999:blog-5862124691901496005.post-53881022366170158502022-07-02T04:00:00.001-07:002022-07-02T04:00:00.187-07:00Day 17/100 Shuf<h2 style="text-align: left;"> Day 17/100 Shuf</h2><h3 style="text-align: left;">Fortune be your Quote of the Day</h3><p><br /></p><p>Part of the coreutils package is a program called "shuf", short for shuffle. This is used to select random lines from a file. It can be a simple, single line or many. There is also a program called "fortune" which will select a random line(s) entry from the data file. I suggest that you look it up, but basically it's a more sophisticated form of shuf. Quote of the Day (QOTD) is also similar to it. Quite a family!</p><p><br /></p><p>Another way to use this program is to generate random numbers. This is where the special number mode is used. You simply specify Lo-Hi range of numbers, and the program will generate random numbers within that range. This works, whether you want the numbers to repeat or not. Quite a feat!</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> for (i--;i && Cnt;Cnt--) {<br /></span><span style="font-family: courier;"> j=i; r=rand()%j;<br /></span><span style="font-family: courier;"> t=Nums[i];Nums[i]=Nums[r];Nums[r]=t;<br /></span><span style="font-family: courier;"> printf("%d\n",Nums[i]);<br /></span><span style="font-family: courier;"> if (Rep==0) i--;<br /></span><span style="font-family: courier;"> }</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>I built this program based off the modified FileGlob program, but it still takes me upward 3 hours to do because of all the different options out there. In fact, I added one more thing: String! You can have it generate a bunch of random strings with number of characters specified with the range option.</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> for (j=strlen(Text);Cnt;Cnt--) {<br /></span><span style="font-family: courier;"> for (i=Lo+rand()%(Hi-Lo+1);i;i--) {<br /></span><span style="font-family: courier;"> r=rand()%j; printf("%c",Text[r]);<br /></span><span style="font-family: courier;"> } printf("\n"); }</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>It's even easier than generating numbers, but this has usefulness as well. You can generate extra large numbers with it, simply by specifying digits as the string, while having the range for the desired number ranges.</p><p><br /></p><p>Of course, dice rolling is easy, too! Let's get some examples:</p><p style="text-align: left;"><span style="font-family: courier;"></span></p><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">3D6: shuf3.c -n 3 -i 1 6 -r<br /></span><span style="font-family: courier;">D100: shuf3.c -i 1 100<br /></span><span style="font-family: courier;">Lotto: shuf.c -i 1 49 -n 5</span></blockquote><span style="font-family: courier;"></span><p></p><p><br /></p><p>So, here's the completed source code:</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">#include <stdio.h><br /></span><span style="font-family: courier;">#include <stdlib.h><br /></span><span style="font-family: courier;">#include <string.h><br /></span><span style="font-family: courier;">#include <time.h></span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">#define CHUNK 65535<br /></span><span style="font-family: courier;">#define MAXLINE 65535<br /></span><span style="font-family: courier;">#define MDFILE 0<br /></span><span style="font-family: courier;">#define MDNUMS 1<br /></span><span style="font-family: courier;">#define MDEND 2<br /></span><span style="font-family: courier;">#define MDSTR 3<br /></span><span style="font-family: courier;">#define MAXSTR 256</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int Mode=MDFILE;<br /></span><span style="font-family: courier;">int NumLo=0;<br /></span><span style="font-family: courier;">int NumHi=9;<br /></span><span style="font-family: courier;">int Cnt=1;<br /></span><span style="font-family: courier;">int Rep=0;<br /></span><span style="font-family: courier;">int Debug=0;<br /></span><span style="font-family: courier;">char Text[MAXSTR]="abc";</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">char *Data;<br /></span><span style="font-family: courier;">int DataSize=0;<br /></span><span style="font-family: courier;">int DataUsed=0;<br /></span><span style="font-family: courier;">FILE *fp;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">char *Lines[MAXLINE];<br /></span><span style="font-family: courier;">int LineUsed=0;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void Init(int argc, char *argv[]) {<br /></span><span style="font-family: courier;"> Data=(char *)malloc(CHUNK);\<br /></span><span style="font-family: courier;"> DataSize=CHUNK;<br /></span><span style="font-family: courier;"> srand(time(NULL));<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void ShowMsg() {<br /></span><span style="font-family: courier;">puts("<br /></span><span style="font-family: courier;">Usage: shuf [OPTION]...<br /></span><span style="font-family: courier;"> or: shuf -i LO-HI [OPTION]...<br /></span><span style="font-family: courier;">Write a random permutation of the input lines to standard output.<br /></span><span style="font-family: courier;">When FILE is -, read standard input<br /></span><span style="font-family: courier;">With no FILE and no -i, 0-9 is default.</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> -i LO HI treat each number LO through HI as an input line<br /></span><span style="font-family: courier;"> -n COUNT output at most COUNT lines<br /></span><span style="font-family: courier;"> -r output lines can be repeated<br /></span><span style="font-family: courier;"> -s STRING Randomize STRING with length according to -i<br /></span><span style="font-family: courier;"> --help display this help and exit<br /></span><span style="font-family: courier;"> --debug Activate DEBUG Mode<br /></span><span style="font-family: courier;">");<br /></span><span style="font-family: courier;">}</span></div><p style="text-align: left;"></p></blockquote><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int ReadData(int argc, char *argv[]) {<br /></span><span style="font-family: courier;"> int c;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> for (int i=1;i<=argc;i++) {<br /></span><span style="font-family: courier;">// puts(argv[i]);</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (i<argc) {<br /></span><span style="font-family: courier;"> if (!strcmp(argv[i],"--help")) {<br /></span><span style="font-family: courier;"> ShowMsg(); exit(0);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strcmp(argv[i],"--debug")) {<br /></span><span style="font-family: courier;"> Debug=1;<br /></span><span style="font-family: courier;"> if (Debug) printf("Debug Mode: %s\n",(Debug)?"ON":"OFF");<br /></span><span style="font-family: courier;"> continue;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strcmp(argv[i],"-r")) {<br /></span><span style="font-family: courier;"> Rep=1;<br /></span><span style="font-family: courier;"> if (Debug) printf("Rep: %d\n",Rep);<br /></span><span style="font-family: courier;"> continue;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp(argv[i],"-n",2)) {<br /></span><span style="font-family: courier;"> Cnt=atoi(argv[++i]);<br /></span><span style="font-family: courier;"> if (Debug) printf("Cnt: %d\n",Cnt);<br /></span><span style="font-family: courier;"> continue;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp(argv[i],"-s",2)) {<br /></span><span style="font-family: courier;"> strcpy(Text,argv[++i]);<br /></span><span style="font-family: courier;"> if (Debug) printf("Text: %s\n",Text);<br /></span><span style="font-family: courier;"> Mode=MDSTR;<br /></span><span style="font-family: courier;"> continue;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp(argv[i],"-i",2)) {<br /></span><span style="font-family: courier;"> NumLo=atoi(argv[++i]);<br /></span><span style="font-family: courier;"> NumHi=atoi(argv[++i]);<br /></span><span style="font-family: courier;"> Mode=MDNUMS;<br /></span><span style="font-family: courier;"> if (Debug) printf("Rng: %d - %d\n",NumLo,NumHi);<br /></span><span style="font-family: courier;"> continue;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> }</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (i==argc) {<br /></span><span style="font-family: courier;"> if (Mode==MDEND) continue;<br /></span><span style="font-family: courier;"> if (Mode==MDNUMS || MDSTR) continue;<br /></span><span style="font-family: courier;"> if (Mode==MDFILE) fp=stdin;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> else if (!strcmp(argv[i],"-")) { fp=stdin; }<br /></span><span style="font-family: courier;"> else if ((fp=fopen(argv[i],"r"))==NULL) {<br /></span><span style="font-family: courier;"> puts("File open Error");<br /></span><span style="font-family: courier;"> return 1;<br /></span><span style="font-family: courier;"> }</span></blockquote><span style="font-family: courier;"></span></div><div><span style="font-family: courier;"><div></div><blockquote><div> Mode==MDEND;</div><div><br /></div><div> while ((c=fgetc(fp))!=EOF) {</div><div> Data[DataUsed++]=c;</div><div> if (DataUsed>=DataSize) {</div><div> Data=(char *)realloc(Data,(DataSize+CHUNK+1));</div><div> DataSize+=CHUNK;</div><div> printf("DataUsed DataSize %d %d\n",DataUsed,DataSize);</div><div> if (Data==NULL) exit(1);</div><div> }</div><div> }</div><div> Data[DataUsed]='\0';</div><div><br /></div><div> if (fp!=stdin) fclose(fp);</div><div> }</div><div> return 0;</div><div>}</div><div></div></blockquote><div></div></span></div><blockquote><span style="font-family: courier;"><div style="text-align: left;"><br /><span style="font-family: courier;">void ProcessData() {<br /></span><span style="font-family: courier;"> int Lo,Hi;<br /></span><span style="font-family: courier;"> int i,j,r;</span><br /><span style="font-family: courier;"> char *t;</span></div></span></blockquote><p><span style="font-family: courier;"></span></p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> puts("ShowLines...");<br /></span><span style="font-family: courier;"> Lines[LineUsed++]=&Data[0];<br /></span><span style="font-family: courier;"> for (i=0;i<DataUsed;i++) {<br /></span><span style="font-family: courier;"> if (Data[i]=='\n') {<br /></span><span style="font-family: courier;"> Data[i]='\0';<br /></span><span style="font-family: courier;"> Lines[LineUsed++]=&Data[i+1];<br /></span><span style="font-family: courier;"> if (LineUsed>=MAXLINE) LineUsed--;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> LineUsed--;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> for (i=LineUsed-1;i && Cnt;Cnt--) {<br /></span><span style="font-family: courier;"> j=i;<br /></span><span style="font-family: courier;"> r=rand()%j;<br /></span><span style="font-family: courier;"> t=Lines[i];Lines[i]=Lines[r];Lines[r]=t;<br /></span><span style="font-family: courier;"> if (Debug) printf("%s %d %d %d\n",Lines[i],i,j,r);<br /></span><span style="font-family: courier;"> else printf("%s\n",Lines[i]);<br /></span><span style="font-family: courier;"> if (Rep==0) i--;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (Debug) printf("%s %d %d %d\n",Lines[i],i,j,r);<br /></span><span style="font-family: courier;"> else printf("%s\n",Lines[i]);</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;">}</span></div><p style="text-align: left;"></p></blockquote><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void CleanUp() {<br /></span><span style="font-family: courier;"> free(Data);<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void RandNums() {<br /></span><span style="font-family: courier;"> int Nums[MAXLINE];<br /></span><span style="font-family: courier;"> int Lo,Hi;<br /></span><span style="font-family: courier;"> int i,j,t,r;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> Lo=NumLo; Hi=NumHi;<br /></span><span style="font-family: courier;"> for (i=0,j=Lo;j<=Hi;j++) {<br /></span><span style="font-family: courier;"> Nums[i++]=j;<br /></span><span style="font-family: courier;"> }</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> for (i--;i && Cnt;Cnt--) {<br /></span><span style="font-family: courier;"> j=i;<br /></span><span style="font-family: courier;"> r=rand()%j;<br /></span><span style="font-family: courier;"> t=Nums[i];Nums[i]=Nums[r];Nums[r]=t;<br /></span><span style="font-family: courier;"> if (Debug) printf("%d %d %d %d\n",Nums[i],i,j,r);<br /></span><span style="font-family: courier;"> else printf("%d\n",Nums[i]);<br /></span><span style="font-family: courier;"> if (Rep==0) i--;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;">// if (Debug) printf("%d %d %d %d\n",Nums[i],i,j,r);<br /></span><span style="font-family: courier;">// else printf("%d\n",Nums[i]);<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void RandStr() {<br /></span><span style="font-family: courier;"> int Nums[MAXLINE];<br /></span><span style="font-family: courier;"> int Lo,Hi;<br /></span><span style="font-family: courier;"> int i,j,t,r;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> Lo=NumLo; Hi=NumHi;</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> for (j=strlen(Text);Cnt;Cnt--) {<br /></span><span style="font-family: courier;"> for (i=Lo+rand()%(Hi-Lo+1);i;i--) {<br /></span><span style="font-family: courier;"> r=rand()%j;<br /></span><span style="font-family: courier;"> if (Debug) printf("%c %d %d %d\n",Text[r],i,j,r);<br /></span><span style="font-family: courier;"> else printf("%c",Text[r]);<br /></span><span style="font-family: courier;"> } printf("\n"); }<br /></span><span style="font-family: courier;">}</span></div><p style="text-align: left;"></p></blockquote><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int main (int argc, char *argv[] ) {<br /></span><span style="font-family: courier;"> int e=0;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (argc<2) { ShowMsg(); return 1; }</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> Init(argc,argv);<br /></span><span style="font-family: courier;"> ReadData(argc,argv);<br /></span><span style="font-family: courier;"> if (Mode==MDNUMS) RandNums();<br /></span><span style="font-family: courier;"> else if (Mode==MDSTR) RandStr();<br /></span><span style="font-family: courier;"> else ProcessData();<br /></span><span style="font-family: courier;"> CleanUp();</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> return e;<br /></span><span style="font-family: courier;">}</span></div><p style="text-align: left;"></p></blockquote><p style="text-align: left;"><br /></p><p>That's quite long! It's not so bad because it's based on earlier FileGlob program, but it's still rather long as far as tiny program is concerned. Like I said, it's all the options that bog it down. Having done professional quality program, though, it would be even worse since professional programmers use frameworks, and it can be rather bothersome, indeed!</p><div><br /></div>Harry Hardjonohttp://www.blogger.com/profile/02635313407341489264noreply@blogger.com0tag:blogger.com,1999:blog-5862124691901496005.post-79316370952926291242022-06-30T04:00:00.004-07:002022-06-30T04:00:00.177-07:00Day 16/100 Split Cat<h2 style="text-align: left;">Day 16/100 Split Cat</h2><h3 style="text-align: left;">Cats are liquid, definitely!</h3><div><br /></div><div>So, I wrote a cat program. For those of you who don't know, "cat" is short for "concatenate", which is a way of saying that you will just jumble everything together. This is such a program. I simply adapted the last program, which was FileGlob, to this one, although I end up deleting most of it, anyway.</div><div><br /></div><div>So, this is the result:</div><div><br /></div><div><span style="font-family: courier;"></span></div><blockquote><div><span style="font-family: courier;"> for (int i=1;i<argc;i++) {</span></div><div><span style="font-family: courier;"> if (!strcmp(argv[i],"-")) ifp=stdin;</span></div><div><span style="font-family: courier;"> else if ((ifp=fopen(argv[i],"r"))==NULL) {</span></div><div><span style="font-family: courier;"> puts("File open Error"); return 1;</span></div><div><span style="font-family: courier;"> }</span></div><div><span style="font-family: courier;"> while (lptr=fgets(Data,MAXSTR,ifp))</span></div><div><span style="font-family: courier;"> ProcessData();</span></div><div><span style="font-family: courier;"> if (ifp!=stdin) fclose(ifp);</span></div><div><span style="font-family: courier;"> }</span></div></blockquote><div><span style="font-family: courier;"></span></div><div><br /></div><div>But it's so easy! Therefore, I added a special option: Split. Actually, this is closer to csplit, which split a file separated by a particular regex. I decided to just split it with a particular file name:</div><div><br /></div><div><span style="font-family: courier;"></span></div><blockquote><div><span style="font-family: courier;">void ProcessData() {</span></div><div><span style="font-family: courier;"> if (sscanf(Data,"WRITE FILE %s",ofname)) {</span></div><div><span style="font-family: courier;"> if (ofp) { fclose(ofp); ofp=NULL; }</span></div><div><span style="font-family: courier;"> ofp=fopen(ofname,"w"); return;</span></div><div><span style="font-family: courier;"> }</span></div><div><span style="font-family: courier;"> printf("%s",Data);</span></div><div><span style="font-family: courier;"> if (ofp) fprintf(ofp,"%s",Data);</span></div><div><span style="font-family: courier;">}</span></div></blockquote><div><span style="font-family: courier;"></span></div><div><br /></div><div>And, uh, that's it! Nothing to it. Too easy!</div><div><span style="font-family: courier;"></span></div><blockquote><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;">#include <stdio.h></span></div><div><span style="font-family: courier;">#include <stdlib.h></span></div><div><span style="font-family: courier;">#include <string.h></span></div></blockquote><div><span style="font-family: courier;"></span></div><div><span style="font-family: courier;"></span></div><blockquote><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;">#define MAXSTR 256</span></div><div><span style="font-family: courier;">char Data[MAXSTR];</span></div><div><span style="font-family: courier;">char ofname[MAXSTR];</span></div><div><span style="font-family: courier;">FILE *ifp;</span></div><div><span style="font-family: courier;">FILE *ofp=NULL;</span></div><div><span style="font-family: courier;">void ProcessData();</span></div></blockquote><div><span style="font-family: courier;"></span></div><div><br /></div><div><span style="font-family: courier;"></span></div><blockquote><div><span style="font-family: courier;">int Init() {</span></div><div><span style="font-family: courier;">return 0;</span></div><div><span style="font-family: courier;">}</span></div></blockquote><div><span style="font-family: courier;"></span></div><div><span style="font-family: courier;"></span></div><blockquote><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;">int ReadData(int argc, char *argv[]) {</span></div><div><span style="font-family: courier;"> char *lptr;</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;"> for (int i=1;i<argc;i++) {</span></div><div><span style="font-family: courier;"> if (!strcmp(argv[i],"-")) ifp=stdin;</span></div><div><span style="font-family: courier;"> else if ((ifp=fopen(argv[i],"r"))==NULL) {</span></div><div><span style="font-family: courier;"> puts("File open Error"); return 1;</span></div><div><span style="font-family: courier;"> }</span></div><div><span style="font-family: courier;"> while (lptr=fgets(Data,MAXSTR,ifp))</span></div><div><span style="font-family: courier;"> ProcessData();</span></div><div><span style="font-family: courier;"> if (ifp!=stdin) fclose(ifp);</span></div><div><span style="font-family: courier;"> }</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;"> return 0;</span></div><div><span style="font-family: courier;">}</span></div></blockquote><div><span style="font-family: courier;"></span></div><div><span style="font-family: courier;"></span></div><blockquote><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;">void ProcessData() {</span></div><div><span style="font-family: courier;"> if (sscanf(Data,"WRITE FILE %s",ofname)) {</span></div><div><span style="font-family: courier;"> if (ofp) { fclose(ofp); ofp=NULL; }</span></div><div><span style="font-family: courier;"> ofp=fopen(ofname,"w"); return;</span></div><div><span style="font-family: courier;"> }</span></div><div><span style="font-family: courier;"> printf("%s",Data);</span></div><div><span style="font-family: courier;"> if (ofp) fprintf(ofp,"%s",Data);</span></div><div><span style="font-family: courier;">}</span></div></blockquote><div><span style="font-family: courier;"></span></div><div><span style="font-family: courier;"></span></div><blockquote><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;">void CleanUp() {</span></div><div><span style="font-family: courier;"> if (ofp) { fclose(ofp); ofp=NULL; }</span></div><div><span style="font-family: courier;">}</span></div></blockquote><div><span style="font-family: courier;"></span></div><div><span style="font-family: courier;"></span></div><blockquote><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;">int main (int argc, char *argv[] ) {</span></div><div><span style="font-family: courier;"> int e=0;</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;"> if (argc<2) {</span></div><div><span style="font-family: courier;"> puts("cat file1 file2 file3 ...");</span></div><div><span style="font-family: courier;"> puts("\"WRITE FILE [filename]\" will write to said file");</span></div><div><span style="font-family: courier;"> return 1;</span></div><div><span style="font-family: courier;"> }</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;"> Init(argc,argv);</span></div><div><span style="font-family: courier;"> ReadData(argc,argv);</span></div><div><span style="font-family: courier;"> CleanUp();</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;"> return e;</span></div><div><span style="font-family: courier;">}</span></div></blockquote><div><span style="font-family: courier;"></span></div><div><br /></div><div>On that note: I did a function prototype declaration for ProcessData(). I could have just move it to the top, but I decided against it.</div><div><br /></div><div><br /></div>Harry Hardjonohttp://www.blogger.com/profile/02635313407341489264noreply@blogger.com0tag:blogger.com,1999:blog-5862124691901496005.post-66943057726897181302022-06-29T04:00:00.005-07:002022-06-29T04:00:00.188-07:00Day 15/100 FileGlob<h2 style="text-align: left;"> Day 15/100 FileGlob</h2><h3 style="text-align: left;">Data Slurping on the go</h3><p><br /></p><p>I kind of delaying this function somewhat. It's not as easy as it looks. In fact, the code that I have here is at amateur hobbyist level, instead of professional level. However, it does the job just fine. Of course, you have to verify data integrity since the program is somewhat fragile.</p><p><br /></p><p>The key point here is that I want to read data all in one go. I realize that I'm reading it per character and that's slow, technically speaking, but it's still fast enough for my use. There are 2 ways for data input: 1. Stdin, which is the Linux pipe. 2. File name on the command line.</p><p><br /></p><p>I want a program that can handle both, and also, not to have to worry too much about allocating enough memory. I still have to watch out for it, but like I said, it's good enough for me.</p><p><br /></p><p>Here is the data globbing section. I had some trouble because I thought sizeof() gives me the size of the allocated memory. Unfortunately, that's not true. So, I have to keep track of it manually.</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> while ((c=fgetc(fp))!=EOF) {<br /></span><span style="font-family: courier;"> Data[DataUsed++]=c;<br /></span><span style="font-family: courier;"> if (DataUsed>=DataSize) {<br /></span><span style="font-family: courier;"> Data=(char *)realloc(Data,(DataSize+CHUNK+1));<br /></span><span style="font-family: courier;"> DataSize+=CHUNK;<br /></span><span style="font-family: courier;"> printf("DataUsed DataSize %d %d\n",DataUsed,DataSize);<br /></span><span style="font-family: courier;"> if (Data==NULL) exit(1);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> Data[DataUsed]='\0';</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>And I cap the data at the end with a string terminator NULL character. This is because the data is by lines, otherwise, I will simply use the DataUsed variables to check the size of the Data.</p><p><br /></p><p>Here is the code that parse the data for lines, and assign them to an array of string pointers:</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> printf("ShowLines...");<br /></span><span style="font-family: courier;"> Lines[LineUsed++]=&Data[0];<br /></span><span style="font-family: courier;"> for (i=0;i<DataUsed;i++) <br /></span><span style="font-family: courier;"> if (Data[i]=='\n') {<br /></span><span style="font-family: courier;"> Data[i]='\0';<br /></span><span style="font-family: courier;"> Lines[LineUsed++]=&Data[i+1];<br /></span><span style="font-family: courier;"> if (LineUsed>=MAXLINE) LineUsed--;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> printf("%d\n",LineUsed);<br /></span><span style="font-family: courier;"> for (i=0;i<LineUsed;i++) <br /></span><span style="font-family: courier;"> printf(">>%s\n",Lines[i]);</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>Since I took a shortcut and neglected to dynamically resize the pointer array, I decided to just ignore the last line. I still count the lines, though, just in case. Alternatively, I can also do that using wc program to check the number of lines.</p><p><br /></p><p>There's really not much to think about, other than keep track of everything, realloc() memory as needed, and not forgetting to free() it at the end of the program. The use of exit() indicates bad flow, and maybe I should use atexit() to clean up the memory.</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">#include <stdio.h><br /></span><span style="font-family: courier;">#include <stdlib.h><br /></span><span style="font-family: courier;">#include <string.h></span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">//#define CHUNK 65535<br /></span><span style="font-family: courier;">#define CHUNK 64<br /></span><span style="font-family: courier;">#define MAXLINE 99</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">char *Data;<br /></span><span style="font-family: courier;">int DataSize=0;<br /></span><span style="font-family: courier;">int DataUsed=0;<br /></span><span style="font-family: courier;">FILE *fp;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">char *Lines[MAXLINE];<br /></span><span style="font-family: courier;">int LineUsed=0;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void Init(int argc, char *argv[]) {<br /></span><span style="font-family: courier;"> Data=(char *)malloc(CHUNK);\<br /></span><span style="font-family: courier;"> DataSize=CHUNK;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int ReadData(int argc, char *argv[]) {<br /></span><span style="font-family: courier;"> int c;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> for (int i=1;i<argc;i++) {<br /></span><span style="font-family: courier;"> puts(argv[i]);<br /></span><span style="font-family: courier;"> if (!strcmp(argv[i],"-")) fp=stdin;<br /></span><span style="font-family: courier;"> else if ((fp=fopen(argv[i],"r"))==NULL) {<br /></span><span style="font-family: courier;"> puts("File open Error");<br /></span><span style="font-family: courier;"> return 1;<br /></span><span style="font-family: courier;"> }</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> while ((c=fgetc(fp))!=EOF) {<br /></span><span style="font-family: courier;"> Data[DataUsed++]=c;<br /></span><span style="font-family: courier;"> if (DataUsed>=DataSize) {<br /></span><span style="font-family: courier;"> Data=(char *)realloc(Data,(DataSize+CHUNK+1));<br /></span><span style="font-family: courier;"> DataSize+=CHUNK;<br /></span><span style="font-family: courier;"> printf("DataUsed DataSize %d %d\n",DataUsed,DataSize);<br /></span><span style="font-family: courier;"> if (Data==NULL) exit(1);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> Data[DataUsed]='\0';</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (fp!=stdin) fclose(fp);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void ProcessData() {<br /></span><span style="font-family: courier;"> int i;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> puts(Data);</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> printf("ShowLines...");<br /></span><span style="font-family: courier;"> Lines[LineUsed++]=&Data[0];<br /></span><span style="font-family: courier;"> for (i=0;i<DataUsed;i++) {<br /></span><span style="font-family: courier;"> if (Data[i]=='\n') {<br /></span><span style="font-family: courier;"> Data[i]='\0';<br /></span><span style="font-family: courier;"> Lines[LineUsed++]=&Data[i+1];<br /></span><span style="font-family: courier;"> if (LineUsed>=MAXLINE) LineUsed--;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> printf("%d\n",LineUsed);<br /></span><span style="font-family: courier;"> for (i=0;i<LineUsed;i++) {<br /></span><span style="font-family: courier;"> printf(">>%s\n",Lines[i]);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void CleanUp() {<br /></span><span style="font-family: courier;"> free(Data);<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int main (int argc, char *argv[] ) {<br /></span><span style="font-family: courier;"> int e=0;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (argc<2) {<br /></span><span style="font-family: courier;"> puts("fileglob [filename]");<br /></span><span style="font-family: courier;"> return 1;<br /></span><span style="font-family: courier;"> }</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> Init(argc,argv);<br /></span><span style="font-family: courier;"> ReadData(argc,argv);<br /></span><span style="font-family: courier;"> ProcessData();<br /></span><span style="font-family: courier;"> CleanUp();</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> return e;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>One more thing: I did this in a rush, and didn't clean it up. So, think of it as a rough note to be referenced, rather than a polished version.</p>Harry Hardjonohttp://www.blogger.com/profile/02635313407341489264noreply@blogger.com0tag:blogger.com,1999:blog-5862124691901496005.post-31984862123739444192022-06-28T04:00:00.000-07:002022-06-28T04:30:18.563-07:00Day 14/100 Turtle Graphic (Simple)<h2 style="text-align: left;"> Day 14/100 Turtle Graphic (Simple)</h2><h3 style="text-align: left;">These turtles are surprisingly fast</h3><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjS3ZmZ8vzt5VdLJNOeyPsepd62kaoSCXl-N7HghIVJ9-WOAXG7_YWy18azZBuGAHOterMKkDrt9mGLnqrZIx6q6KzSEey734kyVVkWt0LTsd2c5iyHB45S3vh08p6jLc6-GbFANgq10dnzbStTyUbuRAoM3zhPm_Ut2RtRnWmoSnBCAIFi0JQAeJGo/s673/test3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="673" data-original-width="454" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjS3ZmZ8vzt5VdLJNOeyPsepd62kaoSCXl-N7HghIVJ9-WOAXG7_YWy18azZBuGAHOterMKkDrt9mGLnqrZIx6q6KzSEey734kyVVkWt0LTsd2c5iyHB45S3vh08p6jLc6-GbFANgq10dnzbStTyUbuRAoM3zhPm_Ut2RtRnWmoSnBCAIFi0JQAeJGo/s320/test3.png" width="216" /></a></div><br /><p><br /></p><p>It annoys me to no end that people are claiming that computer programming is hard and takes years to do. Even more so when I know for sure, that the programming in question is so easy, I have done it with no direction or guidance in an hour. That remains the longest time I spent with this program. I have done it with SmileBasic 3, on Nintendo 3DS, in as little as 10 minutes! Yes, it's that easy!</p><p><br /></p><p>Yet, when I suggested that this problem is good for beginners, people resisted. "That's too complicated!" they say, "It involves a lot of math!" What can I say? The only math involved is sin() and cos(), and you don't really need to understand how they work. You just need to understand how to use it, and that's not really difficult at all. Really, the math is so simple, I was doing it (without properly understanding them until much later) when I was 13 years old! How's that for being a "difficult" problem for kids?</p><p><br /></p><p>I asked as many teachers as I can possibly find to have them teach this, and not only they resisted, some were even felt insulted! I wonder why? Especially noticeable are python users where they insist that importing a turtle graphic library is the <b>only</b> acceptable answer in teaching children how to program this! The only exception is Dan Shiffman, who is an excellent Processing programming language, who featured it in one of his videos. Thanks to him, I have a 'clear' command, that unfortunately does nothing in this case. </p><p><br /></p><p>But really, is the problem really that hard? If you think about it, there's only a few variables:</p><p>Command, Number, Heading (degree), Distance, Angle(radians), and (x0,y0)-(x1,y1) when drawing a line. Include Pen variable if you want to be able to lift the pen off paper and not draw a line when moving the turtle.</p><p><br /></p><p>The Commands are: Clear, Forward, TurnLeft, TurnRight, Pen, and Quit. Only six commands! How long can it be? Clear does nothing, so that's done immediately. Quit simply ends the function, so that's easy!</p><p><br /></p><p>Pen command basically takes the Number variable, 0 for false (don't draw), 1 for true (draw). This can double as color if desired. So, that's easy, too!</p><p><br /></p><p>TurnLeft and TurnRight is basically Heading-=Number and Heading+=Number. How hard is that? Not hard at all!</p><p><br /></p><p>All in all, six commands, and I just did 5 of them really quick and easy! How can people say it's hard? I don't know. Let this be a lesson to you: If you working on a problem, don't worry whether it's hard or not, simply because you don't know how hard it is until you solve it, and once you solve it, you know how to solve it, so how can it be hard?</p><p><br /></p><p>Anyway, here's the core of turtle graphic code:</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">an=map(0.0,(float)he,360.0,0,2*PI);<br /></span><span style="font-family: courier;">tx1=tx0+(float)di*sin(an);<br /></span><span style="font-family: courier;">ty1=ty0-(float)di*cos(an);<br /></span><span style="font-family: courier;">if (pe) SVGDrawLine(tx0,ty0,tx1,ty1);<br /></span><span style="font-family: courier;">tx0=tx1;ty0=ty1;</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>Not that hard, is it? The first line simply maps degree to radians. The only trigonometric functions used are on the second and third line. And this can be confusing. But it's not your fault!</p><p><br /></p><p>You see, I'm using 0 degree as to point North, or upwards to 12 o'clock direction. Mathematicians, however, applied the 0 degree direction to point East, or toward 3 o'clock direction! So, there's a disjoint of application there. I'm no mathematician, so I use the layman's convention. You can use either. It's doesn't really matter at the end, since you can just rotate the turtle 90 degrees.</p><p><br /></p><p>As far as sin() and cos() are concerned, you don't really need to know much more than the curve, and how they map according to distance. The function takes radians, rather annoyingly so, but the math calculations does take radians and converting degree to radians is just a one-liner, so I don't mind it that much.</p><p><br /></p><p>As long as you can see that sin() goes (0)-(1)-(0)-(-1)-(0) for every 90 degrees or PI/2, then all is well. cos() goes (1)-(0)-(-1)-(0)-(1), or basically just shift sin() 90 degrees. That's not difficult at all.</p><p><br /></p><p>Next you want to match the x and y axis with sin() and cos(), and it depends on which direction you want 0 degree to point at! Well, you know my choice. So there.</p><p><br /></p><p>The rest is just taking the scaling the Number to each axis by multiplying it with the values of sin() and cos() for each appropriate axis. Note that in this case, y axis features substraction. This is because in mathematic, the (0,0) origin is at lower left corner whereas in computing, the origin is at upper left corner. If you're confused by this, and I certainly was confused in the beginning, just try it both ways, and you'll see.</p><p><br /></p><p>I'm sorry to say that I have never seen this code shown anywhere else. The two codes that I have seen aren't like mine. The first one limits the angles to 90 degree increment. The second one does allow arbitrary angle, but forgot to subtract the y values! Or maybe that was intentional, since the person who did it was a mathematicians, and he chose East as his zero.</p><p><br /></p><p>Once you have the values of x0,y0 and x1,y1 then all you have to do is draw the line. Put a check to see if the pen variable (pe) is non-zero. After that, you update the values of x0,y0 to that of x1,y1.</p><p><br /></p><p>And that's all there is to it. I hope you will decide to implement this yourself, using any language you wish. Just don't use somebody else's turtle graphic library! Create your own library. Are you a computer programmer, or aren't you?</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">#include <stdio.h><br /></span><span style="font-family: courier;">#include <stdlib.h><br /></span><span style="font-family: courier;">#include <string.h><br /></span><span style="font-family: courier;">#include <math.h></span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;">#define MAXENTRY 10000<br /></span><span style="font-family: courier;">#define MAXSTR 2560<br /></span><span style="font-family: courier;">#define sx0 0<br /></span><span style="font-family: courier;">#define sx1 118<br /></span><span style="font-family: courier;">#define sy0 0<br /></span><span style="font-family: courier;">#define sy1 180</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;">#define PI 3.141528</span></div><p style="text-align: left;"></p></blockquote><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">char Liner[MAXSTR];<br /></span><span style="font-family: courier;">char Data[MAXENTRY][MAXSTR];<br /></span><span style="font-family: courier;">int numentry;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">//turtle<br /></span><span style="font-family: courier;">char co; //command<br /></span><span style="font-family: courier;">int nu; //Number<br /></span><span style="font-family: courier;">int he; //heading<br /></span><span style="font-family: courier;">int di; //distance<br /></span><span style="font-family: courier;">float an; //angle (rad)<br /></span><span style="font-family: courier;">float tx0,ty0,tx1,ty1; //line<br /></span><span style="font-family: courier;">int pe; //pen</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int LoadData() {<br /></span><span style="font-family: courier;"> int num;<br /></span><span style="font-family: courier;"> char *buf;<br /></span><span style="font-family: courier;"> int i=0;</span></div><p></p></blockquote><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> for (i=0;buf=fgets(Liner,MAXSTR,stdin);i++) {<br /></span><span style="font-family: courier;"> strcpy(Data[i],Liner);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> numentry=i;<br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">float map(float x0,float x1, float x2,float y0, float y2) {<br /></span><span style="font-family: courier;"> return y0+((x1-x0)*(y2-y0)/(x2-x0)); //y1<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void SVGDrawLine(float x0,float y0,float x1,float y1) {<br /></span><span style="font-family: courier;"> int t;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">// if (y0>y1) { t=y0; y0=y1; y1=t;<br /></span><span style="font-family: courier;">// t=x0; x0=x1; x1=t; }<br /></span><span style="font-family: courier;"> printf("<line x1=\"%f\" y1=\"%f.0\" x2=\"%f.0\" y2=\"%f.0\" />\n",<br /></span><span style="font-family: courier;"> x0,y0,x1,y1);<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int ProcessData() {<br /></span><span style="font-family: courier;"> int i,j;<br /></span><span style="font-family: courier;"> char c;<br /></span><span style="font-family: courier;"> int n1,n2;<br /></span><span style="font-family: courier;"> char nums[99];</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> i=j=0;<br /></span><span style="font-family: courier;"> while (1) {<br /></span><span style="font-family: courier;"> c=Data[i][j++];<br /></span><span style="font-family: courier;"> switch (c) {<br /></span><span style="font-family: courier;"> case '\n': //newline<br /></span><span style="font-family: courier;"> i++;j=0;<br /></span><span style="font-family: courier;"> break;<br /></span><span style="font-family: courier;"> case 'c': //clearscreen<br /></span><span style="font-family: courier;"> puts("ClearScreen");<br /></span><span style="font-family: courier;"> break;<br /></span><span style="font-family: courier;"> case 'f': //forward<br /></span><span style="font-family: courier;"> strncpy(nums,Data[i]+j,3); j+=3;<br /></span><span style="font-family: courier;"> n1=atoi(nums); di=n1;<br /></span><span style="font-family: courier;"> printf("Forward %d\n",di);</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> an=map(0.0,(float)he,360.0,0,2*PI);<br /></span><span style="font-family: courier;"> tx1=tx0+(float)di*sin(an);<br /></span><span style="font-family: courier;"> ty1=ty0-(float)di*cos(an);<br /></span><span style="font-family: courier;"> if (pe) SVGDrawLine(tx0,ty0,tx1,ty1);<br /></span><span style="font-family: courier;"> tx0=tx1;ty0=ty1;<br /></span><span style="font-family: courier;"> break;<br /></span><span style="font-family: courier;"> case 'l': //turn left<br /></span><span style="font-family: courier;"> strncpy(nums,Data[i]+j,3); j+=3;<br /></span><span style="font-family: courier;"> n1=atoi(nums); he-=n1;<br /></span><span style="font-family: courier;"> printf("Turn Left %d\n",he);<br /></span><span style="font-family: courier;"> break;<br /></span><span style="font-family: courier;"> case 'r': //turn right<br /></span><span style="font-family: courier;"> strncpy(nums,Data[i]+j,3); j+=3;<br /></span><span style="font-family: courier;"> n1=atoi(nums); he+=n1;<br /></span><span style="font-family: courier;"> printf("Turn Right %d\n",he);<br /></span><span style="font-family: courier;"> break;<br /></span><span style="font-family: courier;"> case 'p': //pen<br /></span><span style="font-family: courier;"> strncpy(nums,Data[i]+j,3); j+=3;<br /></span><span style="font-family: courier;"> n1=atoi(nums); pe=n1;<br /></span><span style="font-family: courier;"> printf("Pen %d\n",pe);<br /></span><span style="font-family: courier;"> break;<br /></span><span style="font-family: courier;"> case 'q': //quit<br /></span><span style="font-family: courier;"> puts("Quit");<br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;"> default:<br /></span><span style="font-family: courier;"> break;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></div><p style="text-align: left;"></p></blockquote><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int Init() {<br /></span><span style="font-family: courier;"> co=' ';<br /></span><span style="font-family: courier;"> nu=0; //Number<br /></span><span style="font-family: courier;"> he=0; //heading<br /></span><span style="font-family: courier;"> di=0; //distance<br /></span><span style="font-family: courier;"> an=0; //angle (deg)<br /></span><span style="font-family: courier;"> tx0=59;ty0=90; //line from<br /></span><span style="font-family: courier;"> tx1=tx0;ty1=ty0; //line to<br /></span><span style="font-family: courier;"> pe=1; //pen<br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int main (int argc, char *argv[] ) {<br /></span><span style="font-family: courier;"> int n,i;</span></div><p></p></blockquote><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> Init();<br /></span><span style="font-family: courier;"> LoadData();<br /></span><span style="font-family: courier;"> for (i=0;i<numentry;i++) {<br /></span><span style="font-family: courier;"> printf("%d\t%s",i,Data[i]);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> ProcessData();<br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p><br /></p><p><br /></p>Harry Hardjonohttp://www.blogger.com/profile/02635313407341489264noreply@blogger.com0tag:blogger.com,1999:blog-5862124691901496005.post-83266203784855648822022-06-27T04:00:00.002-07:002022-06-27T04:00:00.192-07:00Day 13/100 Stock Trader<h2 style="text-align: left;"> Day 13/100 Stock Trader</h2><h3 style="text-align: left;">3 White Soldiers and 3 Black Crows</h3><p><br /></p><p>Trading stock can be fun and profitable, but you do need to know what you're doing, or else, you will lose all hopes to achieving dreams beyond your avarice. I suppose you know about hi-lo charts as used in the stock market. I use them, too. However, that's not very interesting. Much more interesting, from learning to code point of view, is the candlestick chart.</p><p><br /></p><p>The wick/tail ends indicates high/low of the day, and the bar indicates the open and close prices of the day. White means closing is higher than open. Black means open is higher than closing. Perfectly simple concept that is really suitable for sightings.</p><p><br /></p><p>The hi-lo chart is really a single line with 2 branches on either side of the line. It takes just as much space as candlestick, but much, much less visible. Take a look at a sample of the candlestick chart:</p><p><br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgalQhGS3unzlQWC0rA47L7IeNS-3AaWTe6VZX2dAhv7Rw1tneWmEd90f8xLJsN3c68dfidsHJgQyOLxeojLN14YzGUJqK-1y3tNbAJ1Rqu5lDq1SOlYEHsBVzIdfKUBz9-KsFcYb9DUB9dhYphH6xqQnLLNUnUm13kGhU98MujI2wauuE9q4Rvr0Si/s673/candle2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="454" data-original-width="673" height="216" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgalQhGS3unzlQWC0rA47L7IeNS-3AaWTe6VZX2dAhv7Rw1tneWmEd90f8xLJsN3c68dfidsHJgQyOLxeojLN14YzGUJqK-1y3tNbAJ1Rqu5lDq1SOlYEHsBVzIdfKUBz9-KsFcYb9DUB9dhYphH6xqQnLLNUnUm13kGhU98MujI2wauuE9q4Rvr0Si/s320/candle2.png" width="320" /></a></div><br /><p><br /></p><p><br /></p><p>Looks like $NFLX is having a bad time lately! Such a shame with all the new shows, too. Anyway, you can easily see the rising prices and the declining prices. 3 white bars in a row are white soldiers, indicating future prosperity. 3 black bars in a row are the black crows, indicating bad times ahead. Unfortunately, I see multiple crows on the chart.</p><p><br /></p><p>The code to draw the candlestick chart is rather involved, as compared to the previous effort. Fortunately, it's rather easy to do, just time consuming due to the amount of data being processed.</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void SVGCandleStick(int n, float o, float h, float l, float c) {<br /></span><span style="font-family: courier;"> int by=20;<br /></span><span style="font-family: courier;"> float b,t;<br /></span><span style="font-family: courier;"> int ay;<br /></span><span style="font-family: courier;"> float r;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> o=map(tmin,o,tmax,35,110);<br /></span><span style="font-family: courier;"> h=map(tmin,h,tmax,35,110);<br /></span><span style="font-family: courier;"> l=map(tmin,l,tmax,35,110);<br /></span><span style="font-family: courier;"> c=map(tmin,c,tmax,35,110);</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> ay=by+(n*3);<br /></span><span style="font-family: courier;"> b=(o>c)?c:o;<br /></span><span style="font-family: courier;"> t=(o>c)?o:c;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> SVGDrawLine(30,ay+1,33,ay+1);</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> SVGDrawLine(l,ay+1,b,ay+1);<br /></span><span style="font-family: courier;"> SVGDrawLine(t,ay+1,h,ay+1);<br /></span><span style="font-family: courier;"> SVGDrawLine(b,ay,t,ay);<br /></span><span style="font-family: courier;"> SVGDrawLine(b,ay+2,t,ay+2);<br /></span><span style="font-family: courier;"> SVGDrawLine(b,ay,b,ay+2);<br /></span><span style="font-family: courier;"> SVGDrawLine(t,ay,t,ay+2);</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (o>c)<br /></span><span style="font-family: courier;"> for (r=0.0;r<=2.0;r+=0.25) {<br /></span><span style="font-family: courier;"> SVGDrawLine(b,ay+r,t,ay+r);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"><br /></span></div><div style="text-align: left;"><span style="font-family: courier;">}</span></div><p style="text-align: left;"></p></blockquote><p style="text-align: left;"><br /></p><p>The first part of the function is to scale the chart appropriately. I simply use millimeters for measuring since it's such a convenient scale. Using inches will be even more time consuming!</p><p><br /></p><p>Then I draw the marks on the horizontal axis. This is followed by the candlestick drawing itself. 2 lines for top and bottom and 4 lines for the candlestick itself. Finally, if open is greater than closing, fill up the box with black.</p><p><br /></p><p>It's more complicated than just drawing a rectangle because the direction of the line drawn matters. The output isn't the screen. Well, it does go to the screen, but I also want to make the output to be compatible with a plotter. That's why I purposely set the direction to draw to the higher X axis direction, never to the opposite direction.</p><p><br /></p><p>This will be more obvious on the next project. However, I will stop here for now. As it is, I simply didn't bother cleaning up the program. Most likely, I will need to visit this program later. Once I set up graphical user interface, that is.</p><p><br /></p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">#include <stdio.h><br /></span><span style="font-family: courier;">#include <stdlib.h><br /></span><span style="font-family: courier;">#include <ctype.h><br /></span><span style="font-family: courier;">#include <string.h></span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">#define MAXSTR 256<br /></span><span style="font-family: courier;">#define MAXENTRY 10000</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int Debug=0;<br /></span><span style="font-family: courier;">float min=5.0;<br /></span><span style="font-family: courier;">float max=20000.0;<br /></span><span style="font-family: courier;">int sca=20;<br /></span><span style="font-family: courier;">char scan[MAXSTR];<br /></span><span style="font-family: courier;">int tstamp=0;<br /></span><span style="font-family: courier;">int dir=0;<br /></span><span style="font-family: courier;">float val=-1;<br /></span><span style="font-family: courier;">int slot,lslot;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">char Date[MAXENTRY][MAXSTR];<br /></span><span style="font-family: courier;">float Open[MAXENTRY];<br /></span><span style="font-family: courier;">float High[MAXENTRY];<br /></span><span style="font-family: courier;">float Low[MAXENTRY];<br /></span><span style="font-family: courier;">float Close[MAXENTRY];<br /></span><span style="font-family: courier;">float Adj[MAXENTRY];<br /></span><span style="font-family: courier;">float Volume[MAXENTRY];<br /></span><span style="font-family: courier;">float tmin=20000.0;<br /></span><span style="font-family: courier;">float tmax=0.0;<br /></span><span style="font-family: courier;">int numentry=0;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void ShowMsg() {<br /></span><span style="font-family: courier;">puts("<br /></span><span style="font-family: courier;">Usage: pnf [OPTION]...<br /></span><span style="font-family: courier;">Display Point and Figure chart given a stock.csv file.<br /></span><span style="font-family: courier;">Min and Max values are not automatically adjusted!<br /></span><span style="font-family: courier;">Default values are:<br /></span><span style="font-family: courier;"> -nN minimum value. Default N0<br /></span><span style="font-family: courier;"> -xN maximum value. Default N200<br /></span><span style="font-family: courier;"> -sN scales. Default N20<br /></span><span style="font-family: courier;"> --help display this help and exit<br /></span><span style="font-family: courier;"> --debug debug info<br /></span><span style="font-family: courier;">");<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int GetOpt(int argc, char *argv[]) {<br /></span><span style="font-family: courier;">int i;<br /></span><span style="font-family: courier;"> for (i=1;i<argc;i++) {<br /></span><span style="font-family: courier;"> if (!strncmp("-n",argv[i],2)) min=atof(argv[i]+2);<br /></span><span style="font-family: courier;"> if (!strncmp("-x",argv[i],2)) max=atof(argv[i]+2);<br /></span><span style="font-family: courier;"> if (!strncmp("-s",argv[i],2)) sca=atoi(argv[i]+2);<br /></span><span style="font-family: courier;"> if (!strncmp("--help",argv[i],6)) {<br /></span><span style="font-family: courier;"> ShowMsg(); return 0;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> if (!strncmp("--debug",argv[i],7)) Debug=1;<br /></span><span style="font-family: courier;"> }</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (Debug) {<br /></span><span style="font-family: courier;"> puts("Debug...");<br /></span><span style="font-family: courier;"> printf("Min: %0.2f\n",min);<br /></span><span style="font-family: courier;"> printf("Max: %0.2f\n",max);<br /></span><span style="font-family: courier;"> printf("Scale: %d\n",sca);<br /></span><span style="font-family: courier;"> }</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></div><p style="text-align: left;"></p></blockquote><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">float map(float x0,float x1, float x2,float y0, float y2) {<br /></span><span style="font-family: courier;"> return y0+((x1-x0)*(y2-y0)/(x2-x0)); //y1<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void SVGDrawLine(float x0,float y0,float x1,float y1) {<br /></span><span style="font-family: courier;"> int t;</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (y0>y1) { t=y0; y0=y1; y1=t;<br /></span><span style="font-family: courier;"> t=x0; x0=x1; x1=t; }<br /></span><span style="font-family: courier;"> printf("<line x1=\"%.2f\" y1=\"%.2f\" x2=\"%.2f\" y2=\"%.2f\" />\n",<br /></span><span style="font-family: courier;"> x0,y0,x1,y1);<br /></span><span style="font-family: courier;">}</span></div><p style="text-align: left;"></p></blockquote><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void SVGDrawHeader() {<br /></span><span style="font-family: courier;"> SVGDrawLine(30,16,114,16);<br /></span><span style="font-family: courier;"> SVGDrawLine(30,16,30,177);<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void SVGCandleStick(int n, float o, float h, float l, float c) {<br /></span><span style="font-family: courier;"> int by=20;<br /></span><span style="font-family: courier;"> float b,t;<br /></span><span style="font-family: courier;"> int ay;<br /></span><span style="font-family: courier;"> float r;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> o=map(tmin,o,tmax,35,110);<br /></span><span style="font-family: courier;"> h=map(tmin,h,tmax,35,110);<br /></span><span style="font-family: courier;"> l=map(tmin,l,tmax,35,110);<br /></span><span style="font-family: courier;"> c=map(tmin,c,tmax,35,110);</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> ay=by+(n*3);<br /></span><span style="font-family: courier;"> b=(o>c)?c:o;<br /></span><span style="font-family: courier;"> t=(o>c)?o:c;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> SVGDrawLine(30,ay+1,33,ay+1);</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> SVGDrawLine(l,ay+1,b,ay+1);<br /></span><span style="font-family: courier;"> SVGDrawLine(t,ay+1,h,ay+1);<br /></span><span style="font-family: courier;"> SVGDrawLine(b,ay,t,ay);<br /></span><span style="font-family: courier;"> SVGDrawLine(b,ay+2,t,ay+2);<br /></span><span style="font-family: courier;"> SVGDrawLine(b,ay,b,ay+2);<br /></span><span style="font-family: courier;"> SVGDrawLine(t,ay,t,ay+2);</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (o>c)<br /></span><span style="font-family: courier;"> for (r=0.0;r<=2.0;r+=0.25) {<br /></span><span style="font-family: courier;"> SVGDrawLine(b,ay+r,t,ay+r);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;">}</span></div><p style="text-align: left;"></p></blockquote><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"><br /></span><span style="font-family: courier;">char *CSV2TSV(char *in) {<br /></span><span style="font-family: courier;"> for (;*in;in++) if (*in==',') *in=' ';<br /></span><span style="font-family: courier;"> return in;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int LoadData() {<br /></span><span style="font-family: courier;"> char line[MAXSTR];</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> numentry=0;<br /></span><span style="font-family: courier;"> while (gets(line)!=NULL) {<br /></span><span style="font-family: courier;"> CSV2TSV(line);<br /></span><span style="font-family: courier;"> sscanf(line,"%s %f %f %f %f %f %f"<br /></span><span style="font-family: courier;"> ,Date[numentry],&Open[numentry],&High[numentry]<br /></span><span style="font-family: courier;"> ,&Low[numentry],&Close[numentry],&Adj[numentry]<br /></span><span style="font-family: courier;"> ,&Volume[numentry]);</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> if (tmin>Low[numentry]) tmin=Low[numentry];<br /></span><span style="font-family: courier;"> if (tmax<High[numentry]) tmax=High[numentry];<br /></span><span style="font-family: courier;"> puts(line);<br /></span><span style="font-family: courier;"> numentry++;<br /></span><span style="font-family: courier;"> }</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int ShowData() {<br /></span><span style="font-family: courier;"> int i,j;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> SVGDrawHeader();</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> for (i=numentry-50,j=i;i<numentry;i++) {<br /></span><span style="font-family: courier;"> printf("%s\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\n"<br /></span><span style="font-family: courier;"> ,Date[i],Open[i],High[i]<br /></span><span style="font-family: courier;"> ,Low[i],Close[i],Adj[i]<br /></span><span style="font-family: courier;"> ,Volume[i]);</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> SVGCandleStick(i-j,Open[i],High[i],Low[i],Close[i]);<br /></span><span style="font-family: courier;"> if (tmin>Low[i]) puts("Error: Low minimum");<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> printf("Min %.2f \t Max %.2f\n",tmin,tmax);<br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int main (int argc, char *argv[] ) {<br /></span><span style="font-family: courier;"> int e=0;<br /></span><span style="font-family: courier;"> char line[MAXSTR];</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> GetOpt(argc, argv);<br /></span><span style="font-family: courier;"> if (gets(line)!=NULL) { //Remove header<br /></span><span style="font-family: courier;"> e=LoadData();<br /></span><span style="font-family: courier;"> if (!e) ShowData();<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> return e;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p><br /></p><p><br /></p><p><br /></p>Harry Hardjonohttp://www.blogger.com/profile/02635313407341489264noreply@blogger.com0tag:blogger.com,1999:blog-5862124691901496005.post-68429815637953621452022-06-25T07:00:00.007-07:002022-06-25T07:00:00.172-07:00Day 12/100 Graphic with SVG<h2 style="text-align: left;"> Day 12/100 Graphic with SVG</h2><h3 style="text-align: left;">It makes a fine line!</h3><p><br /></p><p>So far I have been doing graphic using text only console character, and although it works, it's not really suitable for fine graphics. Of course, having only 80x25 grid doesn't help matters. But what if there's a way to do an ultra high resolution graphic, and do it via text terminal only programs? Turns out there is such a way, albeit not directly. Introducing Scalable Vector Graphic (SVG)!</p><p><br /></p><p>The tutorial that is out there somewhat skimps on the installation process, and proper formatting. I had trouble setting things up. It's not until I finally gave in and installed Inkscape, that I figured out what's going on. The trick is that I play around with the various settings that Inkscape has, and there are several options to do. I chose the simplest, and go from there.</p><p><br /></p><p>The SVG header has viewBox, resolution, and size. There's also default line and fill specification. So far, I mostly do monochrome graphics. Lines and rectangles, so to speak. But I checked out the specification, and it has curves as well, and that is something I'm interested in for future exercises.</p><p><br /></p><p>The point is that you can do really nice graphic using SVG. Check out these pictures:</p><p><br /></p><h3 style="text-align: center;">Line Graph:</h3><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhVvjG29k1wWZuvE0Atzbi176xBq_R92WaHFULx-QsH-Crrmy4cfdTo7elCjo3o91siPqQSbNXri-2jCC2YlGjJCneDq01Q4yFtkRo2_IM2qR3PlEV9soXrwDqeK4e4pwCTAlL49uR9Z6bvz2Cv3kdphca5Q5SsKXnBktIqhbsocNrnZQGg-plS0TS/s673/GraphLine.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="454" data-original-width="673" height="216" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhVvjG29k1wWZuvE0Atzbi176xBq_R92WaHFULx-QsH-Crrmy4cfdTo7elCjo3o91siPqQSbNXri-2jCC2YlGjJCneDq01Q4yFtkRo2_IM2qR3PlEV9soXrwDqeK4e4pwCTAlL49uR9Z6bvz2Cv3kdphca5Q5SsKXnBktIqhbsocNrnZQGg-plS0TS/s320/GraphLine.png" width="320" /></a></div><br /><p><br /></p><h3 style="text-align: center;">Bar Graph:</h3><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBWOGYDg1N2P_SqwJYCF34ab8-UEFl7f3L-WnAynsx2hz44Q_xL8wCORPOyasMdEJS6c36ImDEnRhZr79BLyKx0OGUQmjJ-UH2NNeFAXc7f4lbIhHBqZx3W9nEBrrHQX8R0dvtUq2DtT3_dClept8LEOewF2N12ibNgYbg7L9xg9gvUSWF9RJdmHnw/s673/GraphBar.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="454" data-original-width="673" height="216" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBWOGYDg1N2P_SqwJYCF34ab8-UEFl7f3L-WnAynsx2hz44Q_xL8wCORPOyasMdEJS6c36ImDEnRhZr79BLyKx0OGUQmjJ-UH2NNeFAXc7f4lbIhHBqZx3W9nEBrrHQX8R0dvtUq2DtT3_dClept8LEOewF2N12ibNgYbg7L9xg9gvUSWF9RJdmHnw/s320/GraphBar.png" width="320" /></a></div><br /><p><br /></p><p><br /></p><p>Right now, I don't have a vector based font handy. Sure there is a True Type Font converter, but I'd rather make my own font. After all, this is all for learning purposes. Here is the actual, relevant SVG code, which I later inserted into the SVG framework file.</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void SVGDrawLine(int x0,int y0,int x1,int y1) {<br /></span><span style="font-family: courier;"> int t;<br /></span><span style="font-family: courier;"> printf("<line x1=\"%d.0\" y1=\"%d.0\" x2=\"%d.0\" y2=\"%d.0\" />\n",<br /></span><span style="font-family: courier;"> x0,y0,x1,y1);<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void SVGDrawRect(int x0,int y0,int x1,int y1) {<br /></span><span style="font-family: courier;"> printf("<rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" />\n",<br /></span><span style="font-family: courier;"> x0,y0,(x1-x0),(y1-y0));<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>That's all there is to it. It's not something mysterious at all. If you can do XML, then you can do SVG. All that's left is to fill in the blanks, so to speak. I generated the SVG instructions by modifying my old stock/frequency analysis program. The output is intermingled with ASCII graphic. So, I have to filter them out. I simply use GREP command for that. It's a good thing Raspberry Pi is set up for learning computer programming rather well. I really enjoy using it to create computer programs.</p><p><br /></p><p>Here is the SVG template that I use. Don't ask me what all this stuff do because I don't know! The most important bit is the one in the middle: width, height, and viewBox. I use millimeter because it's more precise than inches, and I don't have to use floating points so much. I inserted the SVG output between the <g> </g> markups, just below the 4 line commands. </p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"><?xml version="1.0"?><br /></span><span style="font-family: courier;"><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.0//EN'<br /></span><span style="font-family: courier;">'http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd'><br /></span><span style="font-family: courier;"><svg xmlns:xlink="http://www.w3.org/1999/xlink" <br /></span><span style="font-family: courier;">style="fill-opacity:1; color-rendering:auto; <br /></span><span style="font-family: courier;">color-interpolation:auto; text-rendering:auto; <br /></span><span style="font-family: courier;">stroke:black; stroke-linecap:square; <br /></span><span style="font-family: courier;">stroke-miterlimit:10; shape-rendering:auto; <br /></span><span style="font-family: courier;">stroke-opacity:0.4; fill:black; <br /></span><span style="font-family: courier;">stroke-dasharray:none; font-weight:normal; <br /></span><span style="font-family: courier;">stroke-width:1; font-family:'Dialog'; font-style:normal; <br /></span><span style="font-family: courier;">stroke-linejoin:miter; font-size:12px; <br /></span><span style="font-family: courier;">stroke-dashoffset:0; image-rendering:auto;" </span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">width="128.0mm" height="190.0mm" <br /></span><span style="font-family: courier;">viewBox="0 0 128.0 190.0" </span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">xmlns="http://www.w3.org/2000/svg"><br /></span><span style="font-family: courier;"><!--Template generated by the Batik Graphics2D SVG Generator--><br /></span><span style="font-family: courier;"><defs id="genericDefs" /></span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"><g><br /></span><span style="font-family: courier;"><line x1="10.0" y1="10.0" x2="118.0" y2="10.0" /><br /></span><span style="font-family: courier;"><line x1="118.0" y1="10.0" x2="118.0" y2="180.0" /><br /></span><span style="font-family: courier;"><line x1="118.0" y1="180.0" x2="10.0" y2="180.0" /><br /></span><span style="font-family: courier;"><line x1="10.0" y1="180.0" x2="10.0" y2="10.0" /><br /></span><span style="font-family: courier;"></g><br /></span><span style="font-family: courier;"></svg></span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>This is just beginning of my journey to do computer graphic using C programming language. Would you believe that there's nobody who can answer the extremely simple question of "How do I draw a dot on screen using C?" I mean, there's tremendous amount of computer graphic libraries, but if you just want to draw a dot on screen, then you're just plain out of luck! Unbelievable!</p><p><br /></p><p>Anyway, enough rambling around. The somewhat confusing and raw experiment using the old, traditional hack-and-slash method is below. That's not a clean software engineering, but like I said, this is only the beginning. Technological research does tend to be messy, since by definition, you don't know what you're doing! That's right. Learning new things involves having your ignorance exposed, at least for a little while. Later on, as you progress, you can refine things better. For now, though, it's just raw.</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">#include <stdio.h><br /></span><span style="font-family: courier;">#include <stdlib.h><br /></span><span style="font-family: courier;">#include <string.h></span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">#define MAXENTRY 10000<br /></span><span style="font-family: courier;">#define MAXSTR 2560<br /></span><span style="font-family: courier;">#define sx0 28<br /></span><span style="font-family: courier;">#define sx1 108<br /></span><span style="font-family: courier;">#define sy0 20<br /></span><span style="font-family: courier;">#define sy1 170<br /></span><span style="font-family: courier;">#define cwidth 40.0</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">char Liner[MAXSTR];<br /></span><span style="font-family: courier;">int Data[MAXENTRY];<br /></span><span style="font-family: courier;">int minEntry=MAXENTRY;<br /></span><span style="font-family: courier;">int maxEntry=0;<br /></span><span style="font-family: courier;">int minValue=MAXENTRY;<br /></span><span style="font-family: courier;">int maxValue=0;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int LoadData() {<br /></span><span style="font-family: courier;"> int num;<br /></span><span style="font-family: courier;"> char *buf;<br /></span><span style="font-family: courier;"> int i=0;</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> while (buf=fgets(Liner,MAXSTR,stdin)) {<br /></span><span style="font-family: courier;"> num=atoi(buf); Data[i]=num;<br /></span><span style="font-family: courier;"> if (minEntry>i) minEntry=i;<br /></span><span style="font-family: courier;"> if (maxEntry<i) maxEntry=i;<br /></span><span style="font-family: courier;"> i++;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></div><p style="text-align: left;"></p></blockquote><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">float map(float x0,float x1, float x2,float y0, float y2) {<br /></span><span style="font-family: courier;"> return (x1-x0)*(y2-y0)/(x2-x0); //y1<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void SVGDrawLine(int x0,int y0,int x1,int y1) {<br /></span><span style="font-family: courier;"> int t;<br /></span><span style="font-family: courier;"> printf("<line x1=\"%d.0\" y1=\"%d.0\" x2=\"%d.0\" y2=\"%d.0\" />\n",<br /></span><span style="font-family: courier;"> x0,y0,x1,y1);<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void SVGDrawRect(int x0,int y0,int x1,int y1) {<br /></span><span style="font-family: courier;"> printf("<rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" />\n",<br /></span><span style="font-family: courier;"> x0,y0,(x1-x0),(y1-y0));<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void DrawHLine(int start, int stop, char mark) {<br /></span><span style="font-family: courier;"> int i;<br /></span><span style="font-family: courier;"> if (start>stop) { i=start; start=stop; stop=i; }<br /></span><span style="font-family: courier;"> for (i=start;i<=stop;i++) putchar(mark);<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void DrawHeader() {<br /></span><span style="font-family: courier;"> printf("\n\n\n");<br /></span><span style="font-family: courier;"> DrawHLine(0,5,' ');<br /></span><span style="font-family: courier;"> printf("%5d",minValue);<br /></span><span style="font-family: courier;"> DrawHLine(15,(72-5),'-');<br /></span><span style="font-family: courier;"> printf("%5d\n",maxValue);<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void GraphBar(char LineMark) {<br /></span><span style="font-family: courier;"> int i,j;<br /></span><span style="font-family: courier;"> int spacer;<br /></span><span style="font-family: courier;"> DrawHeader();<br /></span><span style="font-family: courier;"> for (i=minEntry;i<=maxEntry;i++) {<br /></span><span style="font-family: courier;"> printf("%4d%5d ",i,Data[i]);<br /></span><span style="font-family: courier;"> spacer=(int)map((float)minValue,<br /></span><span style="font-family: courier;"> (float)Data[i],(float)maxValue,0.0,cwidth);<br /></span><span style="font-family: courier;"> DrawHLine(0,spacer,'X'); putchar('\n');<br /></span><span style="font-family: courier;"> SVGDrawRect(<br /></span><span style="font-family: courier;"> sx0,<br /></span><span style="font-family: courier;"> sy0+(i*(sy1-sy0)/(maxEntry-minEntry)),<br /></span><span style="font-family: courier;"> sx0+(int)((float)spacer*2.0),<br /></span><span style="font-family: courier;"> (sy0+2)+(i*(sy1-sy0)/(maxEntry-minEntry))<br /></span><span style="font-family: courier;"> );<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void GraphLine(char LineMark) {<br /></span><span style="font-family: courier;"> int i,j;<br /></span><span style="font-family: courier;"> int spacer;<br /></span><span style="font-family: courier;"> int g0,g1;<br /></span><span style="font-family: courier;"> int l0,l1;</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> DrawHeader();<br /></span><span style="font-family: courier;"> for (i=minEntry;i<=maxEntry;i++) {<br /></span><span style="font-family: courier;"> if (i==minEntry)<br /></span><span style="font-family: courier;"> g0=(int)map((float)minValue,<br /></span><span style="font-family: courier;"> (float)Data[i],(float)maxValue,0.0,cwidth);<br /></span><span style="font-family: courier;"> g1=(int)map((float)minValue,<br /></span><span style="font-family: courier;"> (float)Data[i],(float)maxValue,0.0,cwidth);<br /></span><span style="font-family: courier;"> printf("%4d%5d ",i,g1); l0=g0; l1=g1;<br /></span><span style="font-family: courier;"> if (l0>l1) { j=l0;l0=l1;l1=j; }<br /></span><span style="font-family: courier;"> DrawHLine(0,l0,' '); DrawHLine(l0,l1,'+');<br /></span><span style="font-family: courier;"> putchar('\n');<br /></span><span style="font-family: courier;"> if (i>minEntry) SVGDrawLine(</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> sx0+(g0*2),<br /></span><span style="font-family: courier;"> sy0+((i-1)*(sy1-sy0)/(maxEntry-minEntry)),<br /></span><span style="font-family: courier;"> sx0+(g1*2),<br /></span><span style="font-family: courier;"> sy0+((i)*(sy1-sy0)/(maxEntry-minEntry))<br /></span><span style="font-family: courier;"> );<br /></span><span style="font-family: courier;"> g0=g1;</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int main (int argc, char *argv[] ) {<br /></span><span style="font-family: courier;"> int n,i;</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> for (i=0;i<MAXENTRY;i++) Data[i]=0;<br /></span><span style="font-family: courier;"> LoadData();<br /></span><span style="font-family: courier;"> for (i=minEntry;i<=maxEntry;i++) {<br /></span><span style="font-family: courier;"> if (minValue>Data[i]) minValue=Data[i];<br /></span><span style="font-family: courier;"> if (maxValue<Data[i]) maxValue=Data[i];<br /></span><span style="font-family: courier;"> printf("%d\t%d\n",i,Data[i]);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> printf("\n");<br /></span><span style="font-family: courier;"> printf("Entry: %d\t%d\n",minEntry,maxEntry);<br /></span><span style="font-family: courier;"> printf("Value: %d\t%d\n",minValue,maxValue);</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> GraphBar('X');<br /></span><span style="font-family: courier;"> GraphLine('+');</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></div><p style="text-align: left;"><br /></p><p style="text-align: left;">One more thing: I'm using C for this, but if you're really into Graphic, then I suggest Learning Processing. Dan Shiffman is great at that. You should seek him out!</p></blockquote><p style="text-align: left;"></p>Harry Hardjonohttp://www.blogger.com/profile/02635313407341489264noreply@blogger.com0tag:blogger.com,1999:blog-5862124691901496005.post-79738428589146940362022-06-24T07:00:00.003-07:002022-06-24T07:00:00.184-07:00Day 11/100 Frequency Graph<h2 style="text-align: left;"> Day 11/100 Frequency Graph</h2><h3 style="text-align: left;">Picturing the most likely occurrences</h3><p><br /></p><p>So, I mentioned about doing frequency analysis for the last program, which is Happy Number. I somewhat made it like it's not a trivial thing to do. However, that is not true at all! It is trivial to count occurrences and use an array to do that. You don't even need hash to do it. Just a simple array will do!</p><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int LoadData() {<br /></span><span style="font-family: courier;"> int num;<br /></span><span style="font-family: courier;"> char *buf;</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> while (buf=fgets(Liner,MAXSTR,stdin)) {<br /></span><span style="font-family: courier;"> num=atoi(buf); Data[num]++;<br /></span><span style="font-family: courier;"> if (minEntry>num) minEntry=num;<br /></span><span style="font-family: courier;"> if (maxEntry<num) maxEntry=num;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></div><p style="text-align: left;"></p></blockquote><p style="text-align: left;"><br /></p><p>And that's it! It just doesn't get any easier than that! So, the hour of code is still on-going. What do I do with the rest of the time? Trying to make the program into some eye-catching form, of course. That means graphic.</p><p><br /></p><p>Now, all this time I've been doing, I've been doing it text console. So, certainly there's no graphic screen involved. But not really. If you look at my Point and Figure chart program, you see graphic! Very crude, I admit, but graphic! So, what kind of other graphic can I do with a text screen? </p><p><br /></p><p>There are two kinds of easy chart that comes to mind: Bar chart, and Line chart. Both are easy to do. In fact, some of the early program actually charted Biorhythm. That's graphic. As per usual, I chart it sideways as to allow numerous entries. The range of the charts is fixed, but the number of entries aren't. Therefore, I let the screen scroll to as many entries as available.</p><p><br /></p><p>The difference between the Line chart and the Bar chart is that the Line chart is only a single character, while the Bar chart is filled with graphing character. That's easy enough to do where the programming language allows you to multiply a character and come up with a string with that number of character. C doesn't have that, so I simply made my own. </p><p><br /></p><p>Here is the code for the Bar chart. As you can see, I use a lot of supporting functions. This would be included in libraries, had I use a more sophisticated platform. But I don't, and I don't mind. They're easy enough to do by myself.</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void GraphBar(char LineMark) {<br /></span><span style="font-family: courier;"> int i,j;<br /></span><span style="font-family: courier;"> int spacer;<br /></span><span style="font-family: courier;"> DrawHeader();<br /></span><span style="font-family: courier;"> for (i=minEntry;i<=maxEntry;i++) {<br /></span><span style="font-family: courier;"> printf("%4d%5d ",i,Data[i]);<br /></span><span style="font-family: courier;"> spacer=(int)map((float)minValue<br /></span><span style="font-family: courier;"> ,(float)Data[i],(float)maxValue<br /></span><span style="font-family: courier;"> ,0.0,72.0);<br /></span><span style="font-family: courier;"> DrawHLine(0,spacer,'X'); putchar('\n');<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>As you can see, I use a function called DrawHLine() to draw horizontal line, from start to stop, with a particular character. That's easy enough to do. The current demand for graphic can be easily met just by using a horizontal drawing technique.</p><p><br /></p><p>And here is the Line chart. As you can see, the drawing routine is slighty more complex.</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void GraphLine(char LineMark) {<br /></span><span style="font-family: courier;"> int i,j; int spacer; int g0,g1; int l0,l1;<br /></span><span style="font-family: courier;"> DrawHeader();<br /></span><span style="font-family: courier;"> for (i=minEntry;i<=maxEntry;i++) {<br /></span><span style="font-family: courier;"> if (i==minEntry)<br /></span><span style="font-family: courier;"> g0=(int)map((float)minValue,<br /></span><span style="font-family: courier;"> (float)Data[i],(float)maxValue,0.0,72.0);<br /></span><span style="font-family: courier;"> g1=(int)map((float)minValue,(float)Data[i],<br /></span><span style="font-family: courier;"> (float)maxValue,0.0,72.0);<br /></span><span style="font-family: courier;"> printf("%4d%5d ",i,g1); l0=g0; l1=g1;<br /></span><span style="font-family: courier;"> if (l0>l1) { j=l0;l0=l1;l1=j; }<br /></span><span style="font-family: courier;"> DrawHLine(0,l0,' '); DrawHLine(l0,l1,'+');<br /></span><span style="font-family: courier;"> putchar('\n'); g0=g1;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>The most complicated item in the function is map(). That function basically translate a range into another range. This is very useful in case you want to convert different values such as from meter to kilometer, Fahrenheit to Celcius, or degree to radians. Here, I'm using it to scale the data to fit the screen. It uses a lot of parameters, but conceptually, it's rather simple.</p><p><br /></p><p>Another thing to consider is that I use different variables, g0-g1 and l0-l1. I totally forgot to separate them, but hey, nobody's perfect! Once I use the variables to separate the graph values and the line drawing values, everything works as is.</p><p><br /></p><p>And that's about it. Some programming problems are so simple, I wonder why people keep saying that computer programming is hard. It really depends on the problem, you know?</p><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;">#include <stdio.h><br /></span><span style="font-family: courier;">#include <stdlib.h><br /></span><span style="font-family: courier;">#include <string.h></span><span style="font-family: courier;"><br /></span><span style="font-family: courier;">#define MAXENTRY 10000<br /></span><span style="font-family: courier;">#define MAXSTR 2560</span></div><p style="text-align: left;"></p></blockquote><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">char Liner[MAXSTR];<br /></span><span style="font-family: courier;">int Data[MAXENTRY];<br /></span><span style="font-family: courier;">int minEntry=MAXENTRY;<br /></span><span style="font-family: courier;">int maxEntry=0;<br /></span><span style="font-family: courier;">int minValue=MAXENTRY;<br /></span><span style="font-family: courier;">int maxValue=0;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int LoadData() {<br /></span><span style="font-family: courier;"> int num;<br /></span><span style="font-family: courier;"> char *buf;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> while (buf=fgets(Liner,MAXSTR,stdin)) {<br /></span><span style="font-family: courier;"> num=atoi(buf); Data[num]++;<br /></span><span style="font-family: courier;"> if (minEntry>num) minEntry=num;<br /></span><span style="font-family: courier;"> if (maxEntry<num) maxEntry=num;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;">float map(float x0,float x1, float x2,float y0, float y2) {<br /></span><span style="font-family: courier;"> float y1;</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> y1=(x1-x0)*(y2-y0)/(x2-x0);<br /></span><span style="font-family: courier;"> return y1;<br /></span><span style="font-family: courier;">}</span></div><p style="text-align: left;"></p></blockquote><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void DrawHLine(int start, int stop, char mark) {<br /></span><span style="font-family: courier;"> int i;<br /></span><span style="font-family: courier;"> if (start>stop) { i=start; start=stop; stop=i; }<br /></span><span style="font-family: courier;"> for (i=start;i<=stop;i++) putchar(mark);<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void DrawHeader() {<br /></span><span style="font-family: courier;"> printf("\n\n\n");<br /></span><span style="font-family: courier;"> DrawHLine(0,5,' ');<br /></span><span style="font-family: courier;"> printf("%5d",minValue);<br /></span><span style="font-family: courier;"> DrawHLine(15,(72-5),'-');<br /></span><span style="font-family: courier;"> printf("%5d\n",maxValue);<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void GraphBar(char LineMark) {<br /></span><span style="font-family: courier;"> int i,j;<br /></span><span style="font-family: courier;"> int spacer;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> DrawHeader();<br /></span><span style="font-family: courier;"> for (i=minEntry;i<=maxEntry;i++) {<br /></span><span style="font-family: courier;"> printf("%4d%5d ",i,Data[i]);<br /></span><span style="font-family: courier;"> spacer=(int)map(<br /></span><span style="font-family: courier;"> (float)minValue,(float)Data[i],(float)maxValue<br /></span><span style="font-family: courier;"> ,0.0,72.0);<br /></span><span style="font-family: courier;"> DrawHLine(0,spacer,'X'); putchar('\n');<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">void GraphLine(char LineMark) {<br /></span><span style="font-family: courier;"> int i,j;<br /></span><span style="font-family: courier;"> int spacer;<br /></span><span style="font-family: courier;"> int g0,g1;<br /></span><span style="font-family: courier;"> int l0,l1;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> DrawHeader();<br /></span><span style="font-family: courier;"> for (i=minEntry;i<=maxEntry;i++) {<br /></span><span style="font-family: courier;"> if (i==minEntry)<br /></span><span style="font-family: courier;"> g0=(int)map(<br /></span><span style="font-family: courier;"> (float)minValue,(float)Data[i],(float)maxValue<br /></span><span style="font-family: courier;"> ,0.0,72.0);<br /></span><span style="font-family: courier;"> g1=(int)map(<br /></span><span style="font-family: courier;"> (float)minValue,(float)Data[i],(float)maxValue<br /></span><span style="font-family: courier;"> ,0.0,72.0);<br /></span><span style="font-family: courier;"> printf("%4d%5d ",i,g1);<br /></span><span style="font-family: courier;"> l0=g0; l1=g1;<br /></span><span style="font-family: courier;"> if (l0>l1) { j=l0;l0=l1;l1=j; }<br /></span><span style="font-family: courier;"> DrawHLine(0,l0,' ');<br /></span><span style="font-family: courier;"> DrawHLine(l0,l1,'+');<br /></span><span style="font-family: courier;"> putchar('\n');<br /></span><span style="font-family: courier;"> g0=g1;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int main (int argc, char *argv[] ) {<br /></span><span style="font-family: courier;"> int n,i;</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> for (i=0;i<MAXENTRY;i++) Data[i]=0;<br /></span><span style="font-family: courier;"> LoadData();<br /></span><span style="font-family: courier;"> for (i=minEntry;i<=maxEntry;i++) {<br /></span><span style="font-family: courier;"> if (minValue>Data[i]) minValue=Data[i];<br /></span><span style="font-family: courier;"> if (maxValue<Data[i]) maxValue=Data[i];<br /></span><span style="font-family: courier;"> printf("%d\t%d\n",i,Data[i]);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> printf("\n");<br /></span><span style="font-family: courier;"> printf("Entry: %d\t%d\n",minEntry,maxEntry);<br /></span><span style="font-family: courier;"> printf("Value: %d\t%d\n",minValue,maxValue);</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> GraphBar('X');<br /></span><span style="font-family: courier;"> GraphLine('+');</span><span style="font-family: courier;"><br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></div><div style="text-align: left;"></div></blockquote><div style="text-align: left;"><br /></div><div><div><br /></div><div>One more thing: The program above is customized for the data given. You need to change it a bit to deal with generalized form of data. And if somebody tells you that doing computer graphic in a character terminal is impossible, <b>DON'T BELIEVE IT!</b></div><div><br /></div><div><br /></div><div><br /></div></div>Harry Hardjonohttp://www.blogger.com/profile/02635313407341489264noreply@blogger.com0tag:blogger.com,1999:blog-5862124691901496005.post-38472497324449319892022-06-23T07:00:00.012-07:002022-06-23T07:00:00.194-07:00Day 10/100 Happy Number<h2 style="text-align: left;"> Day 10/100 Happy Number</h2><h3 style="text-align: left;">Happy Numbers are all alike</h3><p><br /></p><p>A happy number is a number that is having the sum of the squares of the digit to equals to 1. If it isn't 1, repeat until it does. Those numbers that does not reach 1, are unhappy numbers.</p><p><br /></p><p>This is LeetCode 202, for those following LeetCode challenges. There are so many solutions. However, like most coding problems, there are different considerations regarding optimizations. Do you optimize for speed, or for memory?</p><p><br /></p><p>This is a question that many programmers don't think about. Most of them simply put everything into hash, and be done with it. A little careful consideration will yield an analysis that basically tells you that the sequence of happy numbers will not exceed that of 999. In fact, on the leetcode official solution, that number was pegged at 243, due to the fact that the next number in sequence after 999 is 243.</p><p><br /></p><p>That's nice. However, that is not good enough for me. Remember the high/low, mountain/valley problem? We only mark the top of the hill, or the bottom of the valley. In those cases, what are the numbers? Here is my first version of happy number program:</p><div style="text-align: left;"><span style="font-family: courier;"></span></div><blockquote><div style="text-align: left;"><span style="font-family: courier;"><br />#include <stdio.h><br />#include <stdlib.h><br />#include <string.h><br />#define MAXENTRY 1000<br />int Mark[MAXENTRY];<br />int happyLast;<br />int happyMax;<br />int happyMin;<br /></span><p style="text-align: left;"><span style="font-family: courier;"><br /></span></p><span style="font-family: courier;">int nextN(int M) {<br /> int N=0;<br /> while (M>0) {<br /> N+=(M%10)*(M%10);<br /> M/=10;<br /> }<br /> return N;<br />}<br /></span></div></blockquote><p> </p><blockquote><div style="text-align: left;"><span style="font-family: courier;">int IsHappy(int N) {<br /> if (N<1) return 0;<br /> while (1) {<br /> if (N<MAXENTRY) {<br /> if (N==1) return 1;<br /> if (Mark[N]) return 0;<br /> Mark[N]=1;<br /> }<br /> happyLast=N; N=nextN(N);<br /> if (happyLast>N && happyMin>N) happyMin=N;<br /> if (happyLast<N && happyMax<N) happyMax=N;<br /> }<br />}<br /></span></div></blockquote><p> </p><blockquote><div style="text-align: left;"><span style="font-family: courier;">int main (int argc, char *argv[] ) {<br /> int n,i;<br /> for (n=50000;n;n--) {<br /> for (i=0;i<MAXENTRY;i++) Mark[i]=0;<br /> happyMin=MAXENTRY; happyMax=0;<br /> if (IsHappy(n)) <br /> printf("%d is happy. %d %d\n",n,happyMin,happyMax);<br /> else <br /> printf("%d is unhappy. %d %d\n",n,happyMin,happyMax);<br /> }<br /> return 0;<br />}</span></div><div style="text-align: left;"><span style="font-family: courier;"><br /></span></div></blockquote>If you notice, I track the minimum and maximum for each happy numbers. This is because I want to see for myself, what the range is for each numbers. You don't see that anywhere else. It's as if people just blindly copy solutions from each others. Speaking of which, here's the other solution, version 2. Diff is between version 1 and version 2:<div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">19a20<br /></span><span style="font-family: courier;">> // printf("%d\n",N);<br /></span><span style="font-family: courier;">28c29,36<br /></span><span style="font-family: courier;">< if (Mark[N]) return 0;<br /></span><span style="font-family: courier;">---<br /></span><span style="font-family: courier;">> if (N==100) return 1;<br /></span><span style="font-family: courier;">> if (N==130) return 1;<br /></span><span style="font-family: courier;">> if (N==2) return 0;<br /></span><span style="font-family: courier;">> if (N==3) return 0;<br /></span><span style="font-family: courier;">> if (N==4) return 0;<br /></span><span style="font-family: courier;">> if (N==145) return 0;<br /></span><span style="font-family: courier;">> if (N==162) return 0;<br /></span><span style="font-family: courier;">> // if (Mark[N]) return 0;</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>As you can see, I no longer use the array to mark visited numbers. This is a great savings for memory. You also see different numbers for happy, such as 100 and 130, as well as for unhappy numbers.</p><p><br /></p><p>By the way, the official solution shows that you only need to check number 4 for unhappy number. Somebody also pointed out that if the number is below 10, then only number 1 and 7 are happy. So that certainly saves some comparison. </p><p><br /></p><p>But is it faster? Let's see the timings.</p><p><br /></p><p>Version 1: This version is the simple version, uses an array.</p><p>user<span style="white-space: pre;"> </span>0m1.044s</p><p><br /></p><p>Version 2: Skips the array. Uses the numbers as above.</p><p>user<span style="white-space: pre;"> </span>0m0.390s</p><p><br /></p><p>Version 3: Only checks number 1 and 4.</p><p>user<span style="white-space: pre;"> </span>0m0.471s</p><p><br /></p><p>Version 4: Removes checks for 3 and 162.</p><p>user<span style="white-space: pre;"> </span>0m0.353s</p><p><br /></p><p>As you can see, the simple version 1 takes the longest, and uses the most memory. Version 2, which takes account of actual minimum and maximum for each number, is not only memory efficient, but also much faster.</p><p><br /></p><p>Version 3, which does only minimal checks, takes no memory and relatively fast, but is still slower than version 2.</p><p><br /></p><p>Version 4, takes a look at the numbers, and removes the least important ones. There's only a solitary 3, and a smatterings 162. The program runs slightly faster without them.</p><p><br /></p><p>Here is the last and most efficient version 4:</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">#include <stdio.h></span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int nextN(int M) {<br /></span><span style="font-family: courier;"> int N=0;<br /></span><span style="font-family: courier;"> while (M>0) {<br /></span><span style="font-family: courier;"> N+=(M%10)*(M%10);<br /></span><span style="font-family: courier;"> M/=10;<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> return N;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int IsHappy(int N) {<br /></span><span style="font-family: courier;"> if (N<1) return 0;<br /></span><span style="font-family: courier;"> while (1) {<br /></span><span style="font-family: courier;"> if (N==1 || N==100 || N==130) return 1;<br /></span><span style="font-family: courier;"> if (N==2 || N==4 || N==145) return 0;<br /></span><span style="font-family: courier;"> N=nextN(N);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">int main (int argc, char *argv[] ) {<br /></span><span style="font-family: courier;"> int n,i;<br /></span><span style="font-family: courier;"> for (n=50000;n;n--) {<br /></span><span style="font-family: courier;"> if (IsHappy(n)) printf("%d is happy\n",n);<br /></span><span style="font-family: courier;"> else printf("%d is unhappy\n",n);<br /></span><span style="font-family: courier;"> }<br /></span><span style="font-family: courier;"> return 0;<br /></span><span style="font-family: courier;">}</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>One more thing:</p><p>That is not the only speed improvement possible. I can also do frequency analysis, looking at the most visited numbers, and check that. But that is an endeavor without end. In case you're wondering, though: 4, 16, 20, 37, 42, 58, 89, 145 are frequently visited numbers, and those are the numbers in the cycle. </p><p>Running time: user<span style="white-space: pre;"> </span>0m0.290s</p><div><br /></div><div><br /></div>Harry Hardjonohttp://www.blogger.com/profile/02635313407341489264noreply@blogger.com0tag:blogger.com,1999:blog-5862124691901496005.post-87041986114742263092022-06-22T07:00:00.006-07:002022-06-22T07:00:00.194-07:00Day 9/100 Higher and Lower<h2 style="text-align: left;"> Day 9/100 Higher and Lower</h2><h3 style="text-align: left;">Levels and Sequences</h3><p><br /></p><p>Last time, on Day 8, I explored LeetCode 845 and 2210. I'm continuing the exploration with LeetCode 300 and 315. I'm going to do 315 first, since that one is easy. All I have to do is basically take the value of each data in an array, and check whether the subsequent value is higher or lower from that initial value.</p><p><br /></p><p>LeetCode 315 specifies only to count the number of lower values, but since it's so easy, I do it both for higher and lower values. Taking the diff from pnf.c (Day 7) and LeetCode 315:</p><p><br /></p><h3 style="text-align: left;">LeetCode 315</h3><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">29a30,35<br /></span><span style="font-family: courier;">> #define MAXENTRY 10000<br /></span><span style="font-family: courier;">> float DataV[MAXENTRY];<br /></span><span style="font-family: courier;">> int DataL[MAXENTRY];<br /></span><span style="font-family: courier;">> int DataH[MAXENTRY];<br /></span><span style="font-family: courier;">> //tstamp is num of entry<br /></span><span style="font-family: courier;">> <br /></span><span style="font-family: courier;">100a107,123<br /></span><span style="font-family: courier;">> void Count() {<br /></span><span style="font-family: courier;">> int i=0;<br /></span><span style="font-family: courier;">> for (i=0;i<=tstamp;i++) {<br /></span><span style="font-family: courier;">> if (i==tstamp) { DataV[i]=Adj; DataL[i]=DataH[i]=0; }<br /></span><span style="font-family: courier;">> if (i<tstamp && DataV[i]>Adj) DataL[i]++;<br /></span><span style="font-family: courier;">> if (i<tstamp && DataV[i]<Adj) DataH[i]++;<br /></span><span style="font-family: courier;">> }<br /></span><span style="font-family: courier;">> }<br /></span><span style="font-family: courier;">> <br /></span><span style="font-family: courier;">> void CountDisp() {<br /></span><span style="font-family: courier;">> int i=0;<br /></span><span style="font-family: courier;">> for (i=0;i<tstamp;i++) {<br /></span><span style="font-family: courier;">> printf("Entry %3d value %f\t LowCount: %3d\tHiCount:%3d\n"<br /></span><span style="font-family: courier;">> ,i,DataV[i],DataL[i],DataH[i]);<br /></span><span style="font-family: courier;">> }<br /></span><span style="font-family: courier;">> }<br /></span><span style="font-family: courier;">> <br /></span><span style="font-family: courier;">106a130,132<br /></span><span style="font-family: courier;">> <br /></span><span style="font-family: courier;">> Count();<br /></span><span style="font-family: courier;">> <br /></span><span style="font-family: courier;">135a162,163<br /></span><span style="font-family: courier;">> <br /></span><span style="font-family: courier;">> CountDisp();</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>That's too easy! I count only 8 line significant difference from the original. Really, there's nothing to explain since it's self explanatory. Anyway, onto LeetCode 300. This time, take LeetCode 315 and patch this diff in:</p><p><br /></p><h3 style="text-align: left;">LeetCode 300</h3><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">111,112c111,112<br /></span><span style="font-family: courier;">< if (i<tstamp && DataV[i]>Adj) DataL[i]++;<br /></span><span style="font-family: courier;">< if (i<tstamp && DataV[i]<Adj) DataH[i]++;<br /></span><span style="font-family: courier;">---<br /></span><span style="font-family: courier;">> if (i<tstamp && DataV[i]>Adj) { DataL[i]++; DataV[i]=Adj; }<br /></span><span style="font-family: courier;">> // if (i<tstamp && DataV[i]<Adj) { DataH[i]++; DataV[i]=Adj; }<br /></span><span style="font-family: courier;">117c117<br /></span><span style="font-family: courier;">< int i=0;<br /></span><span style="font-family: courier;">---<br /></span><span style="font-family: courier;">> int i=0; int max=0;<br /></span><span style="font-family: courier;">119,120c119,121<br /></span><span style="font-family: courier;">< printf("Entry %3d value %f\t LowCount: %3d\tHiCount:%3d\n"<br /></span><span style="font-family: courier;">< ,i,DataV[i],DataL[i],DataH[i]);<br /></span><span style="font-family: courier;">---<br /></span><span style="font-family: courier;">> printf("Entry %3d value %f\t LowCount: %3d \tHiCount: %3d\n",i,DataV[i],DataL[i],DataH[i]);<br /></span><span style="font-family: courier;">> if (max<DataL[i]) max++;<br /></span><span style="font-family: courier;">> // if (max<DataH[i]) max++;<br /></span><span style="font-family: courier;">121a123<br /></span><span style="font-family: courier;">> printf("Longest sequence is: %d\n",max);</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p><br /></p><p>As far as the longest sequence is, I'm only counting one or the other. I could have counted both at once, but that requires an extra storage for DataV[]. The reason being is that although the algorithm is the same, for tracking sequence, the value of DataV[] is updated every time there is a count. And that's about the only significant difference between the two.</p><p><br /></p><p>So, you choose: You can either count the low, the high, or put in an extra array variable to count both.</p><p><br /></p><p>As you can see, leveraging existing program can do wonders for your development time. This is the concept behind "code reuse" although I suppose the term is more closely associated with either code library or objects (in OO paradigm), as opposed to hacking old program to do something new.</p><p><br /></p><p>Experience speaking, sometimes the necessary change is rather drastic, and you need to change the program's core. In that case, it may be easier, faster, and better to just start a new program from scratch.</p><p><br /></p><p>Happy coding!</p><div><br /></div>Harry Hardjonohttp://www.blogger.com/profile/02635313407341489264noreply@blogger.com0tag:blogger.com,1999:blog-5862124691901496005.post-73695722575349140232022-06-21T07:00:00.003-07:002022-06-21T07:00:00.186-07:00Day 8/100 Mountains, Hills, and Valleys<h2 style="text-align: left;"> Day 8/100 Mountains, Hills, and Valleys</h2><h3 style="text-align: left;">Aren't they all the same?</h3><p><br /></p><p><br /></p><p>Today is a special bonus where I'm tackling LeetCode challenge special. What's so special about it? I'm tackling 2 challenges at once! Well, not really. Just one after another. Technically, I can do both at once, though, just so you know.</p><p><br /></p><h2 style="text-align: left;">LeetCode 845</h2><p><br /></p><p>The first challenge is Leet Code 845. This is a special challenge because I was unable to understand the problem properly. Specifically, regarding the nature of a mountain. What should you do if there's plateaus? The example only show a completely flat data, but in the real significant data set, there's no plateau! Everything either goes up or goes down. </p><p><br /></p><p>Obviously, that's not real world. It also makes solving the problem much easier. Specifically, you don't have to keep the state of ascending and descending when encountering the flat level of the mountain. This becomes a problem when real world data have flat inputs. </p><p><br /></p><p>The exercise, then, becomes pointless. Here I am spending a significant amount coding, solving the problem, and the resulting program does not apply in the real world! What kind of pointless exercise is that? Do they really ask these kind of questions in job interviews? Really? What's the point of wasting people's time?</p><p><br /></p><p>The unfortunate thing is that no one really got the right answer, at least after cursory inspection of the solutions. This includes the official solution, which is Two Pointer algorithm. I notice 3 while() functions in the official solution. Isn't that over complicating thing?</p><p><br /></p><p>Last time, I have shown you the Point and Figure chart. Well, now is as good time as any to take advantage of that. Here's the solution as diff from that program:</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">29a30,32<br /></span><span style="font-family: courier;">> int lmtn=0;<br /></span><span style="font-family: courier;">> int mtnx=0;<br /></span><span style="font-family: courier;">> <br /></span><span style="font-family: courier;">119c122,127<br /></span><span style="font-family: courier;">< if (dir<0 && slot>lslot) { showScan(1); dir=1; }<br /></span><span style="font-family: courier;">---<br /></span><span style="font-family: courier;">> if (dir<0 && slot>lslot) {<br /></span><span style="font-family: courier;">> showScan(1); dir=1;<br /></span><span style="font-family: courier;">> if (Debug) printf("(%d)",(tstamp-lmtn));<br /></span><span style="font-family: courier;">> if (mtnx<(tstamp-lmtn)) mtnx=tstamp-lmtn;<br /></span><span style="font-family: courier;">> lmtn=tstamp;<br /></span><span style="font-family: courier;">> }<br /></span><span style="font-family: courier;">135a144<br /></span><span style="font-family: courier;">> printf("\nMax Mountain Range: %d\n",mtnx);</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>That's not difficult at all! Do you notice anything special? There are only 2 variables involved: Max Mountain value (mtnx) and Last Max Mountain value (lmtn). That's O(1) space characteristics. There is also nothing complicated about the loops. I simply use the same looping as the original. So that's O(N) Time. </p><p><br /></p><p>Nothing to it! Can you recognize the algorithm used? </p><p><br /></p><p>Let's go back to Day 6 of the challenge where I did a word count program. The algorithm there is basically: "We're in a space, we're not in a space,..." repeated until end of input. That's a simple, easy to use algorithm. And that's basically what I did. "We're ascending (calculate mtnx), we're descending,..." repeated over and over. And that takes care of things nicely. Bonus: You can do the same for descending to calculate valleys.</p><p><br /></p><p>And that's it! Remember how I said that Word Count program is a significant program? Well, that's because the pattern is very common, and this problem proves it! Not even the solution of official Leet Code answer realized that this problem is as simple and clear as the word count problem! </p><p><br /></p><p><br /></p><h2 style="text-align: left;">LeetCode 2210</h2><p><br /></p><p>The next challenge I'm doing is the Leet Code 2210: Count Hills and Valleys in an Array. There is no official solution at the time of this writing. However, that does not stop me at all. Remember how the last solution is as easy as Word Count? Well, this one is like that.</p><div style="text-align: left;"><span style="font-family: courier;"></span><blockquote><span style="font-family: courier;"><br /></span><span style="font-family: courier;">29a30,32<br /></span><span style="font-family: courier;">> int hills=0;<br /></span><span style="font-family: courier;">> int valls=0;<br /></span><span style="font-family: courier;">> <br /></span><span style="font-family: courier;">118,119c121,122<br /></span><span style="font-family: courier;">< if (dir>0 && slot<lslot) { showScan(1); dir=-1; }<br /></span><span style="font-family: courier;">< if (dir<0 && slot>lslot) { showScan(1); dir=1; }<br /></span><span style="font-family: courier;">---<br /></span><span style="font-family: courier;">> if (dir>0 && slot<lslot) {showScan(1);dir=-1;hills++; }<br /></span><span style="font-family: courier;">> if (dir<0 && slot>lslot) { showScan(1);dir=1;valls++; }<br /></span><span style="font-family: courier;">135a139,140<br /></span><span style="font-family: courier;">> printf("Hills:\t%d\n",hills);<br /></span><span style="font-family: courier;">> printf("Valleys:\t%d\n",valls);</span></blockquote><span style="font-family: courier;"></span></div><p><br /></p><p>The difference is that instead of calculating the period between climbs, we simply noted the direction of travel, and increment the counter every time there is a change of direction. Same data, same algorithm as Leet Code 845.</p><p><br /></p><p>Looking over the solutions, it seems that a lot of people are able to catch on the algorithm. Yet, it is the same class of problems. What makes the previous problem so hard to get right?</p><p><br /></p><p>I can't think of any reason. Then again, I guess this is why some people think that computer programming is hard and takes years to master. They simply didn't think things through.</p><p><br /></p><p>I think my progress went significantly faster when I decided that people are stupid. This means that computer programs are simplistic at its core. Certainly, there are complicated programs, but the numbers are much, much less than you think! In fact, they're pretty rare.</p><p><br /></p><p>Therefore, my advice to you is to not give up. If you run into a complicated program, step back and think about it. What is it that the program is trying to do? And what would be the nearest program that does the same thing? Who knows? Maybe you can simply modify preexisting program to do it.</p><p><br /></p><p>Problem? What problem? There is no problem.</p><div><br /></div>Harry Hardjonohttp://www.blogger.com/profile/02635313407341489264noreply@blogger.com0