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. This one for vim: https://github.com/tomasr/molokai
  3. 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
  4. 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.
  5. 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
  6. 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.
  7. We will allow one username change per account. If you want to change your username please reply to this topic with your desired username, but think carefully as you will not get another chance. The PHP Freaks administration gives username changes low priority, so it might take a while before your username gets changed. We may also reject any request at our discretion if we feel it is inappropriate or will cause too much confusion. Name change requests are just that: requests. We are not in any way obligated to comply with your request, and we may or may not approve the request, with or without reason, at our sole discretion. We will NOT consider name changes for people with less than 100 posts. This rule is to help keep us from being crazy flooded with requests, and also to help us from inadvertently aiding spammers/bots. Do NOT attempt to "spam" your way to 100 posts with random "I agree" or other 1-liner posts. If we determine that you have done this, not only will the request be denied, but you may receive a warning or ban. We will NOT consider a name change to a name that already exists, unless you are in a named member group. This is to serve as a means to keep from being flooded with requests by random people wanting to take over the "shorter" names, and also serve as an additional "perk" for being promoted. NOTE: even if you are in a named member group, it is still unlikely to be approved. An exception might be made if the requested name is determined to be no longer active and there is little to no history with the name in question. For instance, if someone signed up like 10 years ago and made 1 post and hasn't been back since, we might consider releasing the name. But this is at our sole discretion. If by some miracle we do allow you to take over a previously taken name, please note that in order to do this, an automated password reset will occur (an email is sent to the email address in your profile), and your login user name will be changed to the new username. This will only happen for name changes that involve taking over names that previously existed. For regular name changes, you will still use your current login credentials (your original username and current password). Do NOT reply to this topic with things that are not username change requests.
  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. Right. Then just save the file to /dev/null
  16. 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
  17. That's false though. The implication of this would be that noone could learn to understand recursion.
  18. 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.
  19. 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
  20. The brawler gets a defence boost when on low health. Defence was the secondary stat to check when determining who goes first.
  21. 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.
  22. 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.
×
×
  • 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.