DataWraith's recent activity

  1. Comment on I need help with a story that involves math in ~talk

    DataWraith
    Link Parent
    Not super relevant to the thread, but I thought I'd mention it: Isaac Asimov ran with that premise in his 1958 short-stroy The Feeling of Power, where the computers do all the math, but then...

    Maybe in a world where people can't calculate and let the computer do all their calculations

    Not super relevant to the thread, but I thought I'd mention it: Isaac Asimov ran with that premise in his 1958 short-stroy The Feeling of Power, where the computers do all the math, but then someone figures out how to calculate with pencil and paper again. No floating point imprecision in that story, though.

    3 votes
  2. Comment on Fortnightly Programming Q&A Thread in ~comp

    DataWraith
    Link Parent
    I'm glad you found something that works. :) I'm just slightly confused by the design. You're making Game a sub-class of both GameArray and ArrayInput, and that means that it can do both genArray()...

    I'm glad you found something that works. :)

    I'm just slightly confused by the design. You're making Game a sub-class of both GameArray and ArrayInput, and that means that it can do both genArray() and getArray() -- you don't need a separate user ArrayInput anymore, you can just do game.{get,use}Array().

    But it seems... messy to my sensibilities, because Game is now doing multiple things and things get shoved into it from the outside via the playGame method (which is a bit confusing itself, because it does not play the game, it just prepares it).

    If you're interested in further advice: I think it would be better to separate things cleanly into their concerns (without sub-classing), namely (a) making/breaking the puzzle and (b) reading player input.

    I would make a class Puzzle that generates a random code to break in __init__ and does not concern itself with player input. Then you can add methods to that class that only pertain to checking the puzzle's code. For example, one method could calculate the number of black pegs (given a guess as input), one the number of white pegs, and one whether or not the code was cracked (i.e. 4 black pegs). This encapsulates the knowledge about the code(-breaking) in one place and would allow for a relatively simple game loop that does not know anything about the puzzle internals and only concerns itself with gathering user input and forwarding it.

    1 vote
  3. Comment on Fortnightly Programming Q&A Thread in ~comp

    DataWraith
    (edited )
    Link Parent
    To me, using separate objects for everything seems like total overkill. Your objects are wrapping Lists, but you can just use normal functions on Lists without involving objects. I'd suggest the...

    To me, using separate objects for everything seems like total overkill. Your objects are wrapping Lists, but you can just use normal functions on Lists without involving objects. I'd suggest the following solution:

    import random
    
    CHOOSE_ARRAY = ["a", "b", "c", "d"]
    
    def make_code(length = 4):
        # Choose `length` times from CHOOSE_ARRAY, with replacement
        return random.choices(CHOOSE_ARRAY, k = length)
    
    def get_guess():
        # Convert the user input into a list of characters
        return list(input("Input your guess: "))
    
    def compare_guess(code, guess):
        pass # (see spoiler tag)
    
    code = make_code()
    #print(code) # (uncomment for debugging)
    guess = get_guess()
    print("You guessed:  ", guess)
    print("Result:       ", compare_guess(code, guess))
    print("The code was: ", code)
    

    You can add a loop around the last four lines if you want the player to be able to guess multiple times. Since the code is saved in its own variable, it won't change after a guess.

    If you still need to pass something from object to object, you can define a method that takes the thing you want to pass in as an argument:

    class Game:
        [...]
        def use_thing(self, thing):
           # Make use of thing
    
    Spoiler
    def compare_guess(code, guess):
        result = []
        for (code_char, guess_char) in zip(code, guess):
            if code_char == guess_char:
                result.append("✓")
            else:
                result.append("✘")
        return result
    
    1 vote
  4. Comment on RMS addresses the free software community in ~tech

    DataWraith
    Link Parent
    The general case of this is called the Peter principle:

    The general case of this is called the Peter principle:

    people in a hierarchy tend to rise to their "level of incompetence": employees are promoted based on their success in previous jobs until they reach a level at which they are no longer competent

    8 votes
  5. Comment on What programming/technical projects have you been working on? in ~comp

    DataWraith
    Link Parent
    Are you aware of Plaintext Accounting? It defines a relatively simple data format for finances and budgeting -- it is purpose-built and likely to be more ergonomic than JSON/YAML for data entry.

    Are you aware of Plaintext Accounting? It defines a relatively simple data format for finances and budgeting -- it is purpose-built and likely to be more ergonomic than JSON/YAML for data entry.

    3 votes
  6. Comment on If humankind left Earth and came back after 100 years, how much of our digital files would still be readable? in ~talk

    DataWraith
    Link Parent
    I thought I remembered it being in one of The Collected Stories of Vernor Vinge, but that wasn't it. I think I found it again though: it is from his book A Deepness in the Sky. My memory is fuzzy...

    I thought I remembered it being in one of The Collected Stories of Vernor Vinge, but that wasn't it.

    I think I found it again though: it is from his book A Deepness in the Sky. My memory is fuzzy now, but the main thing I remember about it was the fact that the programmer archaeologists kept time in seconds (megaseconds, gigaseconds) and thought that the UNIX epoch marked the time that mankind first set foot on the moon...

    2 votes
  7. Comment on If humankind left Earth and came back after 100 years, how much of our digital files would still be readable? in ~talk

    DataWraith
    (edited )
    Link
    Why would humankind leave and then come back? I think the much more likely scenario is that whatever is considered valuable will get saved and transferred into a new format over time. You can...

    Why would humankind leave and then come back?

    I think the much more likely scenario is that whatever is considered valuable will get saved and transferred into a new format over time. You can convert old data formats into newer ones or write emulators that can deal with the old file format. I like to imagine a future (kind of what Vernor Vinge described in one of his short stories), where "programmer archaeologists" dig through old data and kludge together a stack of emulators within emulators to make some old software work again in order to be applicable to the contemporary problems...

    The real problem IMO is that the most valuable things to store from an archaeological point of view is often the trash, the useless things, that are so commonplace as to be taken for granted.
    For example, Geocities is a treasure trove of information about the ordinary life at the turn of the century, and Yahoo didn't think twice about deleting all of it because it seemed so ordinary -- incidentally it was saved from ruthless deletion by a concerted archival effort, but we're probably not going to be so lucky with everything.

    We can't store everything forever though, so there has to be some sort of curation applied.

    5 votes
  8. Comment on How could I deal with bad actors on my web site? in ~tech

    DataWraith
    Link Parent
    Just wanted to chime in to say that this does work. There was a now-defunct German website that successfully did this via CAPTCHAs. The fun thing about it was that it was randomized, so if you...

    Just wanted to chime in to say that this does work.

    There was a now-defunct German website that successfully did this via CAPTCHAs. The fun thing about it was that it was randomized, so if you used an unwanted phrase in your comment, you'd get a high(er) chance of having to solve a CAPTCHA before the comment goes through. Each additional bad word or phrase would increase the probability, and then they repeated the check after every challenge: if your initial chance to see a CAPTCHA was 90% you actually had a 81% chance of seeing two CAPTCHAs, 72% of seeing three, and so on... it would be kind of evil if it weren't a measure to prevent abuse.

    Some people solved 15 or more challenges in order to post their bile, but it takes quite a bit of time, which is why the system was called Trollbremse (trolling brake). The site owners considered it a win, since these people, while solving CAPTCHAs, were wasting time they could otherwise have used for more trolling...

    7 votes
  9. Comment on Google to stop selling ads based on your specific web browsing in ~tech

    DataWraith
    Link Parent
    This is just an anecdote, but for me the YouTube recommendations used to be pretty good -- until I went ahead and set it to auto-delete the watch history after three months. You'd think three...

    As a side note, another thing of Google's that I'm also surprised is so bad given their data is YouTube recommendations.

    This is just an anecdote, but for me the YouTube recommendations used to be pretty good -- until I went ahead and set it to auto-delete the watch history after three months. You'd think three months are enough data to go on, but now all they suggest is (very) old videos from my subscriptions, most of which I've already seen...

    This also makes me wonder if @Greg has irrelevant ads maybe because he opted out of personalized advertising (which is somewhere in the Google Account settings). I can't really tell whether the setting does anything because I use an adblocker anyway, but it might be one of the reasons for the bad ads if that is the case.

    2 votes
  10. Comment on What programming/technical projects have you been working on? in ~comp

    DataWraith
    Link Parent
    One interesting one I'm aware of is Ant Colony Optimization, which is based on the way foraging ants find paths from their colony to a food source and back. Honestly, there is a bit of a joke...

    One interesting one I'm aware of is Ant Colony Optimization, which is based on the way foraging ants find paths from their colony to a food source and back.

    Honestly, there is a bit of a joke about metaphor inspired meta-heuristics like that and how it seems like a new one is invented every other month...

    4 votes
  11. Comment on What programming/technical projects have you been working on? in ~comp

    DataWraith
    Link
    In keeping with my usual modus operandi of trying a thousand different projects without sticking to any of them, this week I've implemented a Hayek Machine (PDF) in Python. Named after an...

    In keeping with my usual modus operandi of trying a thousand different projects without sticking to any of them, this week I've implemented a Hayek Machine (PDF) in Python.

    Named after an Economist, the Hayek machine is an evolutionary algorithm that can be applied to what the authors call "ultracomplex environments", though it is known to be somewhat difficult to make it work.

    Mine doesn't seem to work very well so far, but the concept is interesting, so I thought I'd post about it.

    As far as I can tell, the Hayek machine was introduced in a paper called "Toward a Model of Mind as a Laissez-Faire Economy of Idiots", and contrary to normal genetic programming systems that are modelled after natural evolution, the Hayek machine is patterned after an economy where corporations create and invest in other corporations, and receive a share of their profits in return.
    The machine mainly consists of a marketplace, where programs bid for the right to act in the world. At each step, the winner of the auction pays the previous 'owner' of the world and can then act in the world (and collect its rewards) for as long as it deems it profitable to do so. Then it auctions off the right to act to a different program.

    Whenever an agent crosses a wealth threshold, it is allowed to create a new agent (through mutation of its program) that it endows with an initial balance from its own coffers. One important property of the Hayek machine is that wealth is conserved -- money does not enter or leave the system during normal operation, with only two exceptions: rewards from the environment increase the overall wealth of the system, while taxes on computation have to be paid for every CPU instruction an agent executes in order to encourage parsimonious use of resources. Ideally those two forces should balance out over time to keep the system in a steady state.

    In theory, the society of agents/corporations/idiots should eventually self-organize and specialize through the bidding process to solve the problem the environment poses. In order to do that, agents need to evolve to bid accurately; if they bid too low, they are outbid by someone else (and eventually starve due to the small tax on computation), and if they bid more than the interaction with the world is worth, they lose money and may eventually go broke. Agents that go broke are, of course, removed from the economy and are thus no longer part of the gene pool.

    My Python implementation uses Linear Genetic Programming to represent the agents' bidding strategies (actions are fixed at 'birth'), and I set it to work on the LunarLander-v2 environment.

    Unfortunately, in all of my attempts of fiddling with the hyperparameters so far, the economy imploded eventually.
    Practically all agents die off because the environment can and does dispense negative rewards that decrease the amount of money in the system, which is contrary to the original design; I'll have to figure out how to limit the damage done by negative rewards (naively clipping them doesn't seem to work), or try to find a different environment that simply does not have negative rewards.

    4 votes
  12. Comment on What is the most difficult or complex thing you have programmed, created, or otherwise made? in ~comp

    DataWraith
    Link Parent
    With Dithering. For what it's worth, if you scan grayscale pages at higher DPI settings, the resulting files will be quite large. In my experience, quantizing to a bi-level image and compressing...

    One bit per pixel? How could you do grays (or shade other colors) if the pixel is either on or off?

    With Dithering.

    For what it's worth, if you scan grayscale pages at higher DPI settings, the resulting files will be quite large. In my experience, quantizing to a bi-level image and compressing with JBIG2 (which is supported in PDF files) gives quite a bit of savings at no perceptible quality loss for typical documents.

    Of course file size is normally a non-issue nowadays, so I don't bother anymore...

    3 votes
  13. Comment on Facebook bans Trump "indefinitely" with Mark Zuckerberg explaining that "the risks of allowing the President to continue to use our service... are simply too great" in ~tech

    DataWraith
    (edited )
    Link Parent
    Nitpick: You wouldn't say Zugwrack in German, that would refer to an already wrecked train, either through accident or normal decomission. The actual term needed would be Zugunglück, which...

    Nitpick: You wouldn't say Zugwrack in German, that would refer to an already wrecked train, either through accident or normal decomission. The actual term needed would be Zugunglück, which literally translates as "unfortunate accident of/involving a train".

    Zeitlupenzugunglück still works as an alliteration and you get the meaning of it (although it is a bit ambiguous grammatically). It would be more common to say Zugunglück in Zeitlupe, which is probably what you were actually going for (i.e. slow motion train wreck). :)

    12 votes
  14. Comment on Tips to use NixOS on a server? in ~comp

    DataWraith
    Link
    I haven't experimented with NixOS on the server yet, but there's a dedicated tool, NixOps, for deploying nix packages to (among other things) cloud servers.

    I haven't experimented with NixOS on the server yet, but there's a dedicated tool, NixOps, for deploying nix packages to (among other things) cloud servers.

    3 votes
  15. Comment on <deleted topic> in ~comp

    DataWraith
    Link Parent
    I think that's called Trust on first use. The Wikipedia article has a good rundown of how different applications make use of the principle and its strengths and weaknesses. The big problem with it...

    I think that's called Trust on first use. The Wikipedia article has a good rundown of how different applications make use of the principle and its strengths and weaknesses.

    The big problem with it is that it only works if you're actually talking to me on the phone on the first call, which isn't guaranteed, since someone could have ursurped the name. Then you'd suspect me to be the fraud when I actually answer the second call. :)

    3 votes
  16. Comment on <deleted topic> in ~comp

    DataWraith
    Link Parent
    That's a noble goal, but I don't think it works with human-readable names. You have to pay for some form of bookkeeping (e.g. Namecoin's Proof of Work or Domain Name Registars). Otherwise the name...

    One of the objectives I had in addition to simply decentralisation was to avoid involving money for having an identity.

    That's a noble goal, but I don't think it works with human-readable names. You have to pay for some form of bookkeeping (e.g. Namecoin's Proof of Work or Domain Name Registars). Otherwise the name can be usurped.

    As for distributing malware, the system makes sure to save files strictly as .txt.

    In your example the .txt file contains an IP address. What if I replace that IP address with, say, a phishing site?

    The downside of this idea is the constant risk of an attacker obtaining the computing power to take over your identity. But this change will be detectable since all files are signed and the attacker will have a different public key than yours.

    Doesn't that defeat the entire purpose though? If I have to get the public key from a trusted source in order to detect tampering, I could just use the public key directly without the associated name. It's true that I could detect when someone usurps a name -- if I trust the previous owner -- but that doesn't help for things like hosting websites, where new people constantly come in.

    A potential solution would be a mechanism that allows a node to "ask" the network if it's the current owner of its identity and have it do this periodically.

    I'm not sure how that helps. If someone else owns the name now, I can do nothing about it, except try to out-compute them again. Trusted contacts will already know my true public key, but new people will be sent to the potentially malicious new owner's site.

    1 vote
  17. Comment on <deleted topic> in ~comp

    DataWraith
    Link
    If you're distributing files based on public/private keys, the Hypercore protocol does that fine. Your added value proposal seems to be in human-memorable names. I'm not sure if I understand...

    If you're distributing files based on public/private keys, the Hypercore protocol does that fine. Your added value proposal seems to be in human-memorable names.

    I'm not sure if I understand completely what you're proposing, but on the surface this sounds incredibly dangerous. If anybody can claim a name, and then the name can be usurped by simply spending more compute power than the original owner, you can take an existing name and their files, usurp the name, and replace the files with stealthy malware.

    This also seems to run afoul of Zooko's triangle; I think you really need a blockchain (such as Namecoin) to solve that problem.

    4 votes
  18. Comment on What programming/technical projects have you been working on? in ~comp

    DataWraith
    Link
    I've been working on a re-imagination of the game Vindinium. Vindinium was a programming game; you wrote a program (in any programming language) that talked to a JSON-API in order to move a Hero...

    I've been working on a re-imagination of the game Vindinium.

    Vindinium was a programming game; you wrote a program (in any programming language) that talked to a JSON-API in order to move a Hero on a small board. The Hero (@1) needs to conquer Gold Mines ($-) to earn gold and can replenish their health at Taverns ([]). Moving next to another hero deals 20 damage to them.

    The rules are very simple, but the ensuing games were always interesting, since you were matched up with unpredictable opponents on procedurally generated maps. Having three opponents makes it that much harder to predict what is going to happen -- you can't use vanilla Alpha-Beta search, for example, because that doesn't work with more than one opponent.

    This is a pretty ambitious project, and, honestly, I'd be surprised if I actually manage to finish it before I get bored, but for now I've completed a random map generator (see example maps below) as well as the game logic and a simple opponent for training purposes. The next step is to actually interface with bots via STDIN; once that works I can get started on writing a server for the game.

    Map #1
    ################################################################
    ##############    ##                        ##    ##############
    ############$-$-  ##    ####  ####  ####    ##  $-$-############
    ########$-                ##        ##                $-########
    ##  $-####    ##        $-##        ##$-        ##    ####$-  ##
    ##  ##      ########        ##    ##        ########      ##  ##
    ##    $-    ##  ##    ####$-##    ##$-####    ##  ##    $-    ##
    ##        $-        ##    ####    ####    ##        $-        ##
    ##  ####$-  ##$-$-####    ##        ##    ####$-$-##  $-####  ##
    ##          ########          ####          ########          ##
    ######  ####    ##  ##  ##  ########  ##  ##  ##    ####  ######
    ####                ##@1##    ####    ##@2##                ####
    ######  ##$-##      ####                ####      ##$-##  ######
    ##      ##        ####      ##    ##      ####        ##      ##
    ##    ##    ##    ##  ####    ####    ####  ##    ##    ##    ##
    ##      ##    []  ##                        ##  []    ##      ##
    ##      ##    []  ##                        ##  []    ##      ##
    ##    ##    ##    ##  ####    ####    ####  ##    ##    ##    ##
    ##      ##        ####      ##    ##      ####        ##      ##
    ######  ##$-##      ####                ####      ##$-##  ######
    ####                ##@3##    ####    ##@4##                ####
    ######  ####    ##  ##  ##  ########  ##  ##  ##    ####  ######
    ##          ########          ####          ########          ##
    ##  ####$-  ##$-$-####    ##        ##    ####$-$-##  $-####  ##
    ##        $-        ##    ####    ####    ##        $-        ##
    ##    $-    ##  ##    ####$-##    ##$-####    ##  ##    $-    ##
    ##  ##      ########        ##    ##        ########      ##  ##
    ##  $-####    ##        $-##        ##$-        ##    ####$-  ##
    ########$-                ##        ##                $-########
    ############$-$-  ##    ####  ####  ####    ##  $-$-############
    ##############    ##                        ##    ##############
    ################################################################
    
    Map #2
    ####################################################################
    ########          $-  ##    ############    ##  $-          ########
    ########$-      ##          ############          ##      $-########
    ##        ##  ##    ##      $-########$-      ##    ##  ##        ##
    ####  ##        ##$-                            $-##        ##  ####
    ##        $-            ####    ####    ####            $-        ##
    ##    $-##  @1    ##  ########################  ##    @2  ##$-    ##
    ##      ##            ########################            ##      ##
    ####    $-##          ########################          ##$-    ####
    ##          ##          ####################          ##          ##
    ##      []$-  ##          ################          ##  $-[]      ##
    ##              ##$-        $-########$-        $-##              ##
    ####$-      $-##  ##  ##  $-  $-####$-  $-  ##  ##  ##$-      $-####
    ##$-              ####                        ####              $-##
    ######      $-      ##  $-  $-        $-  $-  ##      $-      ######
    ##########        ######                    ######        ##########
    ######$-        $-########                ########$-        $-######
    ######$-        $-########                ########$-        $-######
    ##########        ######                    ######        ##########
    ######      $-      ##  $-  $-        $-  $-  ##      $-      ######
    ##$-              ####                        ####              $-##
    ####$-      $-##  ##  ##  $-  $-####$-  $-  ##  ##  ##$-      $-####
    ##              ##$-        $-########$-        $-##              ##
    ##      []$-  ##          ################          ##  $-[]      ##
    ##          ##          ####################          ##          ##
    ####    $-##          ########################          ##$-    ####
    ##      ##            ########################            ##      ##
    ##    $-##  @3    ##  ########################  ##    @4  ##$-    ##
    ##        $-            ####    ####    ####            $-        ##
    ####  ##        ##$-                            $-##        ##  ####
    ##        ##  ##    ##      $-########$-      ##    ##  ##        ##
    ########$-      ##          ############          ##      $-########
    ########          $-  ##    ############    ##  $-          ########
    ####################################################################
    
    Map #3
    ########################################
    ##  $-##    []############[]    ##$-  ##
    ##  @1      ################      @2  ##
    ##  $-    ##    ########    ##    $-  ##
    ##    ##      ############      ##    ##
    ##            $-########$-            ##
    ##$-##  ##$-  ############  $-##  ##$-##
    ######  ##                    ##  ######
    ##########  ##$-##    ##$-##  ##########
    ##########$-######    ######$-##########
    ##########$-######    ######$-##########
    ##########  ##$-##    ##$-##  ##########
    ######  ##                    ##  ######
    ##$-##  ##$-  ############  $-##  ##$-##
    ##            $-########$-            ##
    ##    ##      ############      ##    ##
    ##  $-    ##    ########    ##    $-  ##
    ##  @3      ################      @4  ##
    ##  $-##    []############[]    ##$-  ##
    ########################################
    
    7 votes
  19. Comment on SuperRT - Realtime raytracing on the SNES (walkthrough and technical overview) in ~games

    DataWraith
    Link
    Slightly off-topic, but if you enjoyed this, you might also like Reverse emulating the NES to give it SUPER POWERS!, where custom hardware is added to a NES cartridge to make it capable of...

    Slightly off-topic, but if you enjoyed this, you might also like Reverse emulating the NES to give it SUPER POWERS!, where custom hardware is added to a NES cartridge to make it capable of emulating SNES games.
    The entire channel is fantastic, really. The videos tend to start a bit slow, but they're definitively worth watching.

    1 vote
  20. Comment on This will be a series of questions and/or discussions leading up to implementations. For now, I'd appreciate some general feedback. in ~life

    DataWraith
    (edited )
    Link
    I'd say you can't really get away with not implementing a moderation queue. Apologies if this is too obvious, but to ease the burden, you can implement a variety of auto-moderation rules (Akismet,...

    I'd say you can't really get away with not implementing a moderation queue.

    Apologies if this is too obvious, but to ease the burden, you can implement a variety of auto-moderation rules (Akismet, phrase blacklist, phrase whitelist, maybe even a trainable spam/hate filter).

    My suggestion, though, would be to simply not display a comment at all unless it was approved by a moderator.
    This really kills the joy of posting hateful comments -- they write their comment, and then... nobody ever sees it, so they'll stop doing it.

    You can manually or automatically whitelist commenters after they contribute a good comment. This doesn't necessitate a full-blown login system, you can ask the user to provide their email address (and then don't display or use it in any way other than as ID) or a code phrase that identifies them uniquely.


    Edit: I wanted to expand a bit more on what I imagine.

    First, I didn't make it clear enough that I think you have to mostly manually moderate content -- no filter is perfect, especially with regard to more-or-less subtle trolling.
    However, that doesn't mean that technology can't help expedite the process.

    For example, in addition to a manual blacklist/whitelist, a statistical spam filter can be a line of defense.

    The classification can include a "From:"-Header that specifies the identifier of the commenter (e.g. a HMAC of their name and email).
    Repeatedly commenting users can thus automatically acquire a reputation (as far as the spam filter is concerned), but that reputation will not necessarily override what they are actually saying.

    You can sort the moderation queue by the spam score and quickly approve or reject the lowest/highest scoring comments first. Another advantage of a statistical filter is that they generally come with a way to display the Top/Bottom 10 words or phrases that triggered them. You could highlight those in red/green on the moderation queue message view, so that it becomes easier to see at a glance if the message is malicious or not.

    5 votes