• 2 Posts
  • 479 Comments
Joined 2 years ago
cake
Cake day: June 14th, 2023

help-circle

  • Bear in mind as well that the Scottish government rejected a lot of the privatisation that the remainder of the UK went through, so ‘government’ doesn’t just mean civil servants in offices, it means things like Scottish Forestry and Scottish Water as well. Need to manage small teams of people over very large areas who are frequently out of mobile phone contact, as well as sharing information with subcontractors who will frequently be one-man-band operators who may just have a van and a mobile phone; no laptop, no IT team.

    So ‘convenient’, but also ‘almost nothing else would be practicable’.



  • C++ / Boost

    Ah, cunning - my favourite one so far this year, I think. Nothing too special compared to the other solutions - floods the map using Dijkstra, then checks “every pair” for how much of a time saver it is. 0.3s on my laptop; it iterates through every pair twice since it does part 1 and part 2 separately, which could easily be improved upon.

    spoiler
    #include <boost/log/trivial.hpp>
    #include <boost/unordered/unordered_flat_map.hpp>
    #include <boost/unordered/unordered_flat_set.hpp>
    #include <cstddef>
    #include <fstream>
    #include <limits>
    #include <queue>
    #include <stdexcept>
    
    namespace {
    
    using Loc = std::pair<int, int>;
    using Dir = std::pair<int, int>;
    template <class T>
    using Score = std::pair<size_t, T>;
    template <class T>
    using MinHeap = std::priority_queue<Score<T>, std::vector<Score<T>>, std::greater<Score<T>>>;
    using Map = boost::unordered_flat_set<Loc>;
    
    auto operator+(const Loc &l, const Dir &d) {
      return Loc{l.first + d.first, l.second + d.second};
    }
    
    auto manhattan(const Loc &a, const Loc &b) {
      return std::abs(a.first - b.first) + std::abs(a.second - b.second);
    }
    
    auto dirs = std::vector<Dir>{
        {0,  -1},
        {0,  1 },
        {-1, 0 },
        {1,  0 }
    };
    
    struct Maze {
      Map map;
      Loc start;
      Loc end;
    };
    
    auto parse() {
      auto rval = Maze{};
      auto line = std::string{};
      auto ih = std::ifstream{"input/20"};
      auto row = 0;
      while (std::getline(ih, line)) {
        for (auto col = 0; col < int(line.size()); ++col) {
          auto t = line.at(col);
          switch (t) {
          case 'S':
            rval.start = Loc{col, row};
            rval.map.insert(Loc{col, row});
            break;
          case 'E':
            rval.end = Loc{col, row};
            rval.map.insert(Loc{col, row});
            break;
          case '.':
            rval.map.insert(Loc{col, row});
            break;
          case '#':
            break;
          default:
            throw std::runtime_error{"oops"};
          }
        }
        ++row;
      }
      return rval;
    }
    
    auto dijkstra(const Maze &m) {
      auto unvisited = MinHeap<Loc>{};
      auto visited = boost::unordered_flat_map<Loc, size_t>{};
    
      for (const auto &e : m.map)
        visited[e] = std::numeric_limits<size_t>::max();
    
      visited[m.start] = 0;
      unvisited.push({0, {m.start}});
    
      while (!unvisited.empty()) {
        auto next = unvisited.top();
        unvisited.pop();
    
        if (visited.at(next.second) < next.first)
          continue;
    
        for (const auto &dir : dirs) {
          auto prospective = Loc{next.second + dir};
          if (!visited.contains(prospective))
            continue;
          auto pscore = next.first + 1;
          if (visited.at(prospective) > pscore) {
            visited[prospective] = pscore;
            unvisited.push({pscore, prospective});
          }
        }
      }
    
      return visited;
    }
    
    using Walk = decltype(dijkstra(Maze{}));
    
    constexpr auto GOOD_CHEAT = 100;
    
    auto evaluate_cheats(const Walk &walk, int skip) {
      auto rval = size_t{};
      for (auto &start : walk) {
        for (auto &end : walk) {
          auto distance = manhattan(start.first, end.first);
          if (distance <= skip && end.second > start.second) {
            auto improvement = int(end.second) - int(start.second) - distance;
            if (improvement >= GOOD_CHEAT)
              ++rval;
          }
        }
      }
      return rval;
    }
    
    } // namespace
    
    auto main() -> int {
      auto p = parse();
      auto walk = dijkstra(p);
      BOOST_LOG_TRIVIAL(info) << "01: " << evaluate_cheats(walk, 2);
      BOOST_LOG_TRIVIAL(info) << "02: " << evaluate_cheats(walk, 20);
    }
    

  • I’d probably go with a “kitchen” metaphor here.

    The executable for a program is a list of instructions for the CPU to execute. Windows and Linux gaming machines will usually use x64. Most of the instructions are logic eg. how to add numbers together, what comparisons to make, what to copy from one place to another; and they’re exactly the same on both Windows and Linux, you can run them as-is.

    Some instructions ask the operating system to do things, like open a file to read. Windows and Linux do these quite differently, but you know how one works then you can change it to the equivalent ask for the other machine. Making the translation takes a moment, but some things are faster on Linux than Windows, so it’s not very easy to generalise as to whether it’ll be faster overall to do certain things. The really important operating system calls for games tend to be messages to pass to the GPU, and the Proton team have put a lot of work into making these as fast as possible.

    If you think of it like following a food recipe, then given the ingredients you’d expect that most people would produce exactly the same meal by following it. Most of the steps will be exactly the same for everyone. However, if a step requires a piece of equipment that you don’t have, then it might take longer to follow the recipe if you’ve got to make do with different stuff. Similarly, you might be able to prepare things quicker if you’ve got a whole pile of restaurant-level gear and can do some of the steps differently.










  • Bear in mind that the gallon we use is different from the US gallon, too:

    • a UK gallon is eight (imperial) pints of 20 fluid ounces, so 4.54 litres
    • a US gallon is 231 cubic inches, so 3.79 litres

    The reason that I thought American car fuel economy was so terrible as a child is partly because UK mpg is +20% on US mpg for the same car on the same fuel. But also, because American car fuel economy is so terrible.


  • A mace is a tool to defeat plate armour - can still cause bludgeoning damage and concussion just by smacking it hard enough. Regular soldiers would probably be wearing mail, which can be defeated by a piercing sword, and peasants would have a gambeson at the very best, which can be defeated with slicing swords or (preferably) axes.

    No, these are weapons for killing aristocrats.


  • A shame that all the really early 3D games use their own software rendering engines, and aren’t so amenable to being “cranked up” like later games when accelerators became common.

    Get some of the early freescape games like Total Eclipse or Castle Master, early cyberpunk games like Interphase, or even Frontier: Elite II running in big resolutions with silky framerates and insane draw distances, I’d be so pleased.




  • That’s not correct, I’m afraid.

    Thermal expansion is proportional to temperature; it’s quite significant for ye olde spinning rust hard drives but the mechanical stress affects all parts in a system. Especially for a gaming machine that’s not run 24/7 - it will experience thermal cycling. Mechanical strength also decreases with increasing temperature, making it worse.

    Second law of thermodynamics is that heat only moves spontaneously from hotter to colder. A 60° bath can melt more ice than a 90° cup of coffee - it contains more heat - but it can’t raise the temperature of anything above 60°, which the coffee could. A 350W graphics card at 20° couldn’t raise your room above that temperature, but a 350W graphics card at 90° could do so. (The “runs colder” card would presumably have big fans to move the heat away.)