Jump to content

Daniel0

Staff Alumni
  • Posts

    11,885
  • Joined

  • Last visited

Everything posted by Daniel0

  1. It isn't random. It's pseudorandom. Given the same seed, you'll always get the same number. PRNGs generate numbers that are difficult to predict without the seed so they look random.
  2. 1+i
  3. This one for vim: https://github.com/tomasr/molokai
  4. I'm not sure it's worth adding one more example in a new language. Any Turing-complete language will be able to express the Y combinator (though some prettier than others). LOL. I know what kind of face I'd be getting if I said that to my colleagues because I named all my functions y($x) x($y). Well, if you know what the Y combinator is, then you'll understand the naming convention of $f and $g. If you don't, giving them other names wouldn't help you at all
  5. It's the Y combinator, so it's called "Y" on purpose. It computes the fixpoint in (untyped) λ-calculus. $f and $g are just functions, so they're properly named as well by standard mathematical conventions. Given to Y is a function that given a "partial" Fibonacci function returns a new function that can compute one more recursive step of the Fibonacci function, so to speak (that is, if it can compute f(n), then the new function can compute f(n+1)). The fixpoint of this function is the "full" Fibonacci function. The Y combinator allows you to express any recursive computation without using recursion.
  6. Nah... a perfect script should stick as close to λ-calculus and functional programming as possible. For instance, clearly this is the most elegant way to print the first 10 Fibonacci numbers: <?php function Y($f) { $ff = function($f) { return $f($f); }; // PHP doesn't allow function call chaining return $ff( function ($g) use ($f) { return $f(function() use ($g) { return call_user_func_array($g($g), func_get_args()); }); } ); } $fib = Y(function($fib) { return function($n) use ($fib) { return $n === 0 ? 0 : ($n === 1 ? 1 : $fib($n-1) + $fib($n-2)); }; }); function tabulate($n, $f) { $g = Y(function($a) use ($n, $f) { return function($l, $m) use ($n, $a, $f) { return $n === $m ? $l : $a(array_merge([$f($m)], $l), $m + 1); }; }); return $g([], 0); } $disp = function($f, $n) { printf("f(%d) = %d\n", $n, $f($n)); }; tabulate(10, function($n) use ($fib, $disp) { $disp($fib, $n); }); Output: f(0) = 0 f(1) = 1 f(2) = 1 f(3) = 2 f(4) = 3 f(5) = 5 f(6) = 8 f(7) = 13 f( = 21 f(9) = 34
  7. You don't need to understand the first part of my post to become a PHP programmer. I only touched the tip of the iceberg. If you find it interesting and you'd like to learn about compiler theory, I would recommend you to read a book or take a course on compilers (the latter would likely include the former as well though). I'm a computer science student, so compiler and formal language theory are some of the subjects I deal with, but you don't need to become a computer scientist to become a web developer. I don't expect you to understand all of it at this point, but there should be enough keywords for you to research should you decide to look at it further. An understanding of the HTTP protocol is pretty essential if you want to become a web developer though, even if you at first only have a rudimentary understanding of it.
  8. That's not entirely true. The following outputs hello: <?php test(); function test() { echo 'hello'; } If it was strictly line by line, top to bottom, you couldn't execute this because the test() function didn't exist yet. To understand why this is the case, you need to understand how interpreters/compilers work. The work is typically split into multiple, distinct steps. The first step is called lexical analysis, which is the process of turning a series of characters into a series of "tokens". For instance, the string echo in PHP corresponds to the T_ECHO token in PHP (the list of tokens in PHP can be found at http://php.net/tokens). The part of the program that does this is typically called a lexer or a tokenizer. The string "echo 1+1" would result in the following tokens: T_ECHO, T_WHITESPACE, T_LNUMBER, +, T_LNUMBER. The next step is syntax analysis (also called parsing), which takes a series of tokens as input and gives an "abstract syntax tree" (AST) as output. It does this using a predefined grammar that consists of a set of "productions" consisting of "terminals" and "non-terminals". Typically you would describe this grammar using a formalized notation such as (Extended) Backus-Naur Form ((E)BNF) and use a parser generator to get a parser, because hand-coding it is tedious and error prone. The above example string would result in the following tree: T_ECHO | + / \ T_LNUMBER(1) T_NUMBER(2) A simple EBNF grammar for a mathematical expression (integers only) with the common arithmetic operators and grouping with parentheses could look like this (precedence rules work from top to bottom): digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; number = digit, { digit } ; expr = number | plus | minus | div | mult | group ; group = "(", expr, ")" ; mult = expr, "*", expr ; div = expr, "/", expr ; plus = expr, "+", expr ; minus = expr, "-", expr ; Here, each line is a production, each thing in quotes is called a terminal and the others are called non-terminals. Given a set of productions, you can using a process called derivation. There exist multiple strategies for doing this, e.g. LL(1) parsing, SLR parsing, etc. After the parsing, you can have a type checker, e.g. to ensure that both operands of an arithmetic operator are guaranteed to be numeric. PHP does runtime type inference, so it doesn't have a type checker. There is no difference between a compiler and an interpreter up until this point. At this point, an interpreter will evaluate the AST by recursively traversing it. A compiler will transform the AST into a another, typically lower level, language. Again, this would be using recursive traversal. This may be something like LLVM, bytecode for JVM, assembler for some CPU architecture or something else. In theory, there is nothing preventing you from taking a PHP AST and turning it into Python source code, or English prose describing what is going on if it would be executed. When evaluating the AST, you may create a lookup table consisting of in-scope variables, functions, etc. Again, this is not entirely true. To understand why this is the case, you need to understand how the HTTP protocol works. HTTP is a stateless protocol defined in RFC 2616, which works by sending a request (with some headers) and getting a response in return (with some headers). To login, my user agent (e.g. a browser) could send a request like this: POST /login.php HTTP/1.1 Host: www.example.com User-Agent: whatever Content-Type: application/x-www-form-urlencoded ***possibly more headers*** username=Daniel&password=s3cret When the web server receives this request, it may "forward" it to PHP so it can generate an appropriate response. Assuming the credentials given are correct, you may choose to set some cookie so you can remember him (remember, HTTP is stateless and all requests are entirely separated) and you may use the Location response header to indicate to the client that it should go somewhere else when it is done. However, this doesn't stop the execution of your script. Doing this could be problematic as well. You might still have some cleaning up to do (closing connections to other places, releasing file locks, etc.), or you may have more headers you want to send. If you want the execution to stop, you'll have to explicitly do it using die()/exit() or simply make sure that there are no executable statements after. When you have done this, the web server may send something like the following request back over the same TCP socket: HTTP/1.1 200 OK Location: http://www.example.com/index.php Set-Cookie: session_id=kasdfusd89f79ads8f7g Actually, RFC 2616 says that a user agent "MUST NOT" automatically redirect as a result of a Location response header without user intervention if the request was not GET or HEAD, but most browsers seem to ignore that. At any rate, the Location is only a suggestion for the client to retrieve the new resource. The client is free to ignore it. You may verify that this is true by placing the following file in a web-accessible directory and requesting it using a browser: <?php header('Location: http://www.google.com/'); file_put_contents('new_file.txt', 'Was not here before...'); ?> Assuming the web server has write permissions in that directory, you should find a new file called new_file.txt in that directory even though your browser was redirected to Google.
  9. Actually, speed is a factor on StackOverflow. If you're late to the party, your chance of getting many upvotes is diminished.
  10. Sure, it's always good getting multiple points of views on an issue.
  11. Hmm... but majority vote isn't necessarily a measure of quality or correctness. I'm not convinced that this is the solution. Hypothetical scenario: User A asks a question, user B responds with a half-decent answer and gets 5 votes for that. Now user C provides a much better answer (let's just for the sake of argument suppose that we by some objective standard can determine that). User A returns to his post and observes that user B has 5 votes and user C has 0, indicating that the answer provided by user B is better, contrary to reality. Now what?
  12. I'm sure the person responsible will feel god's wrath and burn in hell.
  13. Can't blame him. Whether your stuff gets implemented is dependent on that there is not some idiot on the top who vetos because it's against some stupid axiom he made for that special occasion. There may be a million votes for the proposol, and none against, but that doesn't matter if someone decides that his personal vision is more important than a community decision. That certainly does happen, but if you never even attempted to submit the patches, it's guaranteed that they won't be accepted. I was basing my rant on particular encounters with certain members of the PHP Group. I can't be bothered going into details, but as a result I ultimately decided that I no longer wanted to contribute. Of course there needs to be leadership, but there is a such thing as bad leadership.
  14. Can't blame him. Whether your stuff gets implemented is dependent on that there is not some idiot on the top who vetos because it's against some stupid axiom he made for that special occasion. There may be a million votes for the proposol, and none against, but that doesn't matter if someone decides that his personal vision is more important than a community decision.
  15. Sure it is. Just ask Sony
  16. Right. Then just save the file to /dev/null
  17. That's false though. The implication of this would be that noone could learn to understand recursion. You're like a real-life Sheldon, you know that right? right? Hmm... didn't catch that reference
  18. That's false though. The implication of this would be that noone could learn to understand recursion.
  19. I'm not really sure I understand the (potential) attack vector you're worried about. Are you saying that requests made to resource A (no SSL) will result in a 301 response redirecting to resource B using SSL? You only have a security issue if the user makes a request with confidential information to resource A. Example 1: User sends a GET request to http://www.example.com/ and gets redirected to https://www.example.com/. User fills a form that submits via POST to https://www.example.com/login.php. This is no problem. The login credentials are protected by the SSL layer. Example 2: User sends a POST request to http://www.example.com/login.php with login information, and gets redirected to https://www.example.com/login.php submitting the same data via POST (note that RFC 2616 actually prohibits automatic redirection in this case, but no (or very few) browsers actually honors this). This is a problem, because the first time the information was transmitted, it was unencrypted. If none of those examples describe your scenario, try using a packet sniffer to look at what data is being transmitted when you make the requests.
  20. 0 * * * * wget "http://mysite.com/test-cron.php" -O /dev/null If it's on the same server, just run it directly though: 0 * * * * php /path/to/test-cron.php
  21. The brawler gets a defence boost when on low health. Defence was the secondary stat to check when determining who goes first.
  22. Warriors' stats can change during the course of the battle, so you're not necessarily first because you were first in the first round. Easily fixed by sorting inside the loop instead of outside though.
  23. I suppose I might as well post the solution I made yesterday as well. I didn't bother creating a web front end, so run it from a terminal... <?php class Player { private $name; private $health; private $attack; private $defence; private $speed; private $evade; private $maxHealth; public function __construct($name, $health, $attack, $defence, $speed, $evade) { $this->name = $name; $this->health = $this->maxHealth = $health; $this->attack = $attack; $this->defence = $defence; $this->speed = $speed; $this->evade = $evade; } public function isAlive() { return $this->health > 0; } public function getName() { return $this->name; } public function getHealth() { return $this->health; } public function getMaxHealth() { return $this->maxHealth; } public function getAttack() { return $this->attack; } public function getDefence() { return $this->defence; } public function getSpeed() { return $this->speed; } public function getEvade() { return $this->evade / 100; } public function attack(Player $opponent) { if (!$opponent->doEvadeRoll($this)) { $opponent->wound($this->getAttack() - $opponent->getDefence(), $opponent); } } public function wound($hp, Player $opponent) { $this->health = max(0, $this->health - $hp); } public function heal($hp) { $this->health = min($this->getMaxHealth(), $this->health + $hp); } public function doEvadeRoll(Player $opponent) { return mt_rand(1, 100) <= $this->evade; } public function __toString() { return sprintf('%s (%d)', $this->getName(), $this->getHealth()); } } class Ninja extends Player { public function __construct($name) { parent::__construct($name, mt_rand(40, 60), mt_rand(60, 70), mt_rand(20, 30), mt_rand(90, 100), mt_rand(30, 100) ); } public function getAttack() { $attack = parent::getAttack(); if (mt_rand(1, 100) <= 5) { $attack *= 2; } return $attack; } } class Samurai extends Player { public function __construct($name) { parent::__construct($name, mt_rand(60, 100), mt_rand(75, 80), mt_rand(35, 40), mt_rand(60, 80), mt_rand(30, 40) ); } public function doEvadeRoll(Player $opponent) { $evaded = parent::doEvadeRoll($opponent); if ($evaded && mt_rand(1, 100) <= 10) { $this->heal(10); } return $evaded; } } class Brawler extends Player { public function __construct($name) { parent::__construct($name, mt_rand(90, 100), mt_rand(65, 75), mt_rand(40, 50), mt_rand(40, 65), mt_rand(30, 35) ); } public function getDefence() { $def = parent::getDefence(); if ($this->getHealth()/$this->getMaxHealth() < 0.2) { $def += 10; } return $def; } } class Game { private $player1; private $player2; private $maxRounds; private $rounds; public function __construct(Player $player1, Player $player2, $maxRounds = 30) { $this->player1 = $player1; $this->player2 = $player2; $this->maxRounds = $maxRounds; $this->rounds = 0; } public function gameOver() { return $this->rounds == $this->maxRounds || !$this->player1->isAlive() || !$this->player2->isAlive(); } public function getWinner() { if (!$this->gameOver()) { throw new Exception('Game not over yet.'); } if (!$this->player2->isAlive()) { return $this->player1; } else if (!$this->player1->isAlive()) { return $this->player2; } else { return null; // draw } } private function comparePlayers(Player $a, Player $b) { $s1 = $a->getSpeed(); $s2 = $b->getSpeed(); if ($s1 === $s2) { return $a->getDefence() - $b->getDefence(); } else { return $s1 - $s2; } } public function doRound() { if ($this->gameOver()) { throw new Exception('Cannot do more rounds when game is over.'); } ++$this->rounds; $players = array($this->player1, $this->player2); usort($players, array($this, 'comparePlayers')); $players[0]->attack($players[1]); $players[1]->attack($players[0]); } public function getRound() { return $this->rounds + 1; } } $classes = array('Ninja', 'Samurai', 'Brawler'); list($p1, $p2) = array_rand($classes, 2); $player1 = new $classes[$p1]($classes[$p1]); $player2 = new $classes[$p2]($classes[$p2]); $game = new Game($player1, $player2, 30); while (!$game->gameOver()) { echo 'Round ' . $game->getRound() . ':' . PHP_EOL; echo $player1 . PHP_EOL; echo $player2 . PHP_EOL; echo PHP_EOL; $game->doRound(); } $winner = $game->getWinner(); if ($winner === null) { echo 'Draw.'; } else { echo 'Winner: ' . $winner->getName(); } echo PHP_EOL; I estimate that I used ~40 minutes.
  24. I don't mean to sound condescending, but I was a teaching assistant on a first-year university level programming course (Object Oriented Programming and Design). The course load was 7.5 ECTS-credits. I would have expected my students to be able to solve that problem. Indeed the exam was creating a Tron-like game with a GUI and simple AI strategies for computer based players using Java. The only programming course prior to that one was Introduction to Programming, which used functional programming, so the for many students, it was the first time they had to program imperatively. Having these expectations of first-year students, I would certainly expect that anyone who has completed a four year degree that claims to teach programming would be able to solve this problem with no trouble at all. That's the impression I got as well. I suppose this would mean OP's degree has what I called a "shitty curriculum". That's not his fault of course. You cannot really know what is essential to be taught in a particular field if you're not already experienced with that field.
  25. Of course you can learn to program in a school. Imperative programming and functional programming is based on models of computations known as the Turing machine and the λ-calculus respectively, both "invented" in the 1930s. Object-oriented programming became more widespread with the emergence of Smalltalk in the 1970s, but the concept of objects started in academia over a decade earlier. Imperative programming works by manipulating the state of the computer until a particular set of variables/registers have the desired value. This hasn't changed at all. There hasn't really been much development from the von Neumann architecture, which is really the practical "implementation" of a Turing machine. If a school doesn't teach its students how to manipulate computers (not necessarily by introducing them to the aforementioned theory) by breaking problems down to things that can be handled by those models of computations, then it simply has a shitty curriculum. Sure, if a school only teaches trivia about a particular programming language's API then there is a problem, but the fundamental problem in this thread isn't that he is having trouble because of API changes during the course of his education, but that he hasn't learned to program, something which transcends the choice of programming language. If you've learned to program object-orientedly in Java, then you shouldn't have much trouble programming in another object-oriented programming language (e.g. C#). Sure, the syntax might be a bit different and you'll have to get used to the different API, but thsoe are things are encyclopeadic knowledge, things that can be looked up. You cannot look up "how to program". The only time you'll have real trouble is if you switch to a programming language in an unfamiliar paradigm. For programming, I would at any time recommend an theory based education instead of a vocational one, i.e. an education that teaches the "whys" instead of the "hows". If you understand the theory, then it's (fairly) easy applying that in many different scenarios (such as picking up a new object-oriented programming language when you already understand OOP). Note that I'm not advocating a strictly bottom-up approach though. I'm not saying that you should introduce people to things like Turing machines before you start teaching them programming, nor that they necessarily need to know what that is. However, they do need to understand what it essentially means to program. As for keeping up with particular technologies, that's the students own responsibility.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.