spit-evil-olive-tips's recent activity

  1. Comment on Day 6: Lanternfish in ~comp.advent_of_code

    spit-evil-olive-tips
    Link
    part 1 I did via brute force. when part 2 was revealed, I just updated my script to simulate 256 days, let it run, and then started writing part 2 using the non-brute-force approach. Part 1 def...

    part 1 I did via brute force. when part 2 was revealed, I just updated my script to simulate 256 days, let it run, and then started writing part 2 using the non-brute-force approach.

    Part 1
    def main():
        with open('006.txt') as file:
            fishes = [int(age) for age in file.readline().split(',')]
    
        for day in range(80):
            print(f'day {day}: {len(fishes)}')
            for i, timer in list(enumerate(fishes)):
                if fishes[i] == 0:
                    fishes.append(8)
                    fishes[i] = 6
                else:
                    fishes[i] = timer - 1
    
        print(len(fishes))
    
    main()
    
    Part 2
    from collections import defaultdict
    
    
    def main():
        with open('006.txt') as file:
            fishes = [int(age) for age in file.readline().split(',')]
    
        population = defaultdict(int)
        for timer in fishes:
            population[timer] += 1
    
        for day in range(256):
            print(f'day {day}: {dict(population)}')
            new_population = defaultdict(int)
            for timer, count in population.items():
                if timer == 0:
                    new_population[8] = count
                    new_population[6] += count
                else:
                    new_population[timer-1] += count
    
            population = new_population
    
        print(sum(population.values()))
    
    main()
    

    when I killed the brute-force script (after about 11 minutes), it was only on day 155, with a fish population of 237636802. its memory consumption was around 17gb. based on the ratio of that population to the population on my final day, it would have taken ~112 terabytes of RAM to host all 256 days of the brute-force simulation (to say nothing of the runtime)

    meanwhile my more optimized part 2 runs in 27 milliseconds and uses negligible memory compared to the overhead of the Python runtime.

    5 votes
  2. Comment on Day 5: Hydrothermal Venture in ~comp.advent_of_code

    spit-evil-olive-tips
    Link Parent
    we used the exact same regex! I definitely agree that judicious use of regexes is much better than manual string-splitting and parsing. Perl and other languages have given them a bad name by...

    we used the exact same regex! I definitely agree that judicious use of regexes is much better than manual string-splitting and parsing. Perl and other languages have given them a bad name by encouraging their overuse.

    another neat trick, along the lines of the nested defaultdict, is that you can use tuples as dictionary keys because they're immutable:

    >>> d = dict()
    >>> key = [1, 2]
    >>> d[key] = True
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: unhashable type: 'list'
    >>> key = (1, 2)
    >>> d[key] = True
    >>> d
    {(1, 2): True}
    

    so in this case it's possible to represent the grid as a single layer dict where the keys are (x, y) tuples, as I did in my "part 3" solution. the possible downside to that is that you can no longer easily iterate a single row of the grid. that doesn't matter for this particular problem but it might in other cases.

    also, a minor Pythonic note, min() and max() both accept an unlimited number of arguments, so min([y1, y2],) can be simplified to min(y1, y2)

    >>> min([69, 420])
    69
    >>> min(69, 420)
    69
    >>> min(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
    1
    
    2 votes
  3. Comment on Day 5: Hydrothermal Venture in ~comp.advent_of_code

    spit-evil-olive-tips
    Link
    Part 1 my initial solution was horribly inefficient, but got the job done. from dataclasses import dataclass import re RIDGE_RE = re.compile('(\d+),(\d+) -> (\d+),(\d+)') @dataclass class Ridge:...
    Part 1

    my initial solution was horribly inefficient, but got the job done.

    from dataclasses import dataclass
    import re
    
    RIDGE_RE = re.compile('(\d+),(\d+) -> (\d+),(\d+)')
    
    @dataclass
    class Ridge:
        x1: int
        y1: int
        x2: int
        y2: int
    
        @classmethod
        def parse(cls, line):
            match = RIDGE_RE.match(line)
            coordinates = [int(value) for value in match.groups()]
            return cls(*coordinates)
    
        def get_points(self):
            if self.x1 == self.x2:
                start = min(self.y1, self.y2)
                end = max(self.y1, self.y2)
                return [(self.x1, y) for y in range(start, end+1)]
            elif self.y1 == self.y2:
                start = min(self.x1, self.x2)
                end = max(self.x1, self.x2)
                return [(x, self.y1) for x in range(start, end+1)]
            else:
                return []
    
        @staticmethod
        def get_overlap(r1, r2):
            points1 = set(r1.get_points())
            points2 = set(r2.get_points())
            if points1 == points2:
                return []
            else:
                overlap = points1.intersection(points2)
                return overlap
    
    def main():
        with open('005.txt') as file:
            lines = file.readlines()
    
        ridges = [Ridge.parse(line) for line in lines]
        all_overlaps = set()
        for ridge1 in ridges:
            for ridge2 in ridges:
                if ridge1 != ridge2:
                    overlap = Ridge.get_overlap(ridge1, ridge2)
                    all_overlaps.update(overlap)
    
        print(sorted(all_overlaps))
        print(len(all_overlaps))
    
    if __name__ == '__main__':
        main()
    

    it takes ~17 seconds to run on my full puzzle input, but I was running on the example input while I was writing it, so it didn't make much of a difference to the overall time.

    Part 2

    biggest stumbling block I had with part 2 was getting this logic to work correctly for diagonal lines of both positive and negative slope.

    @@ -26,7 +26,11 @@
                 end = max(self.x1, self.x2)
                 return [(x, self.y1) for x in range(start, end+1)]
             else:
    -            return []
    +            delta_x = 1 if self.x2 > self.x1 else -1
    +            delta_y = 1 if self.y2 > self.y1 else -1
    +            range_x = range(self.x1, self.x2+delta_x, delta_x)
    +            range_y = range(self.y1, self.y2+delta_y, delta_y)
    +            return [(x, y) for x, y in zip(range_x, range_y)]
     
         @staticmethod
         def get_overlap(r1, r2):
    
    Part 3

    my initial solution worked, but it's much slower than it needs to be, mainly because of the O(n^2) algorithm of looping through every possible pair of ridges and computing their intersection.

    a "not sure why I didn't think of doing it this way initially" refactoring is to just keep counts of the overlapping points:

    @@ -1,3 +1,4 @@
    +from collections import Counter
     from dataclasses import dataclass
     import re
     
    @@ -32,30 +33,21 @@
                 range_y = range(self.y1, self.y2+delta_y, delta_y)
                 return [(x, y) for x, y in zip(range_x, range_y)]
     
    -    @staticmethod
    -    def get_overlap(r1, r2):
    -        points1 = set(r1.get_points())
    -        points2 = set(r2.get_points())
    -        if points1 == points2:
    -            return []
    -        else:
    -            overlap = points1.intersection(points2)
    -            return overlap
     
     def main():
         with open('005.txt') as file:
             lines = file.readlines()
     
         ridges = [Ridge.parse(line) for line in lines]
    -    all_overlaps = set()
    -    for ridge1 in ridges:
    -        for ridge2 in ridges:
    -            if ridge1 != ridge2:
    -                overlap = Ridge.get_overlap(ridge1, ridge2)
    -                all_overlaps.update(overlap)
     
    -    print(sorted(all_overlaps))
    -    print(len(all_overlaps))
    +    points = Counter()
    +    for ridge in ridges:
    +        for point in ridge.get_points():
    +            points[point] += 1
    +
    +    overlap = sum(1 for point, count in points.items() if count > 1)
    +    print(overlap)
    +
    

    run time went from ~30 seconds to ~180 milliseconds.

    2 votes
  4. Comment on Day 4: Giant Squid in ~comp.advent_of_code

    spit-evil-olive-tips
    Link
    first problem where object-orientation really makes sense to use. Part 1 import re BOARD_RE = re.compile('(\d+)', re.MULTILINE) SIZE = 5 class Board: def __init__(self, entries): assert...

    first problem where object-orientation really makes sense to use.

    Part 1
    import re
    
    BOARD_RE = re.compile('(\d+)', re.MULTILINE)
    
    SIZE = 5
    
    class Board:
        def __init__(self, entries):
            assert len(entries) == (SIZE ** 2)
            self.entries = entries
            self.marked = [False] * len(entries)
    
        @classmethod
        def parse(cls, input):
            entries = [int(entry) for entry in BOARD_RE.findall(input)]
            return cls(entries)
    
        def mark(self, value):
            for i, entry in enumerate(self.entries):
                if entry == value:
                    self.marked[i] = True
    
        def get_row(self, index):
            return range(index*SIZE, (index+1) * SIZE)
    
        def get_col(self, index):
            return range(index, SIZE*SIZE, SIZE)
    
        def is_winner(self):
            for i in range(SIZE):
                row = self.get_row(i)
                if all(self.marked[index] for index in row):
                    return True
    
                col = self.get_col(i)
                if all(self.marked[index] for index in col):
                    return True
    
            return False
    
        def sum_of_unmarked(self):
            sum = 0
            for index, entry in enumerate(self.entries):
                if not self.marked[index]:
                    sum += entry
            return sum
    
    
    def main():
        with open('004.txt') as file:
            numbers = [int(number) for number in file.readline().split(',')]
            board_lines = file.read()
    
        boards = []
        for board_string in board_lines.split('\n\n'):
            board = Board.parse(board_string)
            boards.append(board)
    
        for number in numbers:
            for board in boards:
                board.mark(number)
    
            for board in boards:
                if board.is_winner():
                    print(number * board.sum_of_unmarked())
                    return
    
    main()
    
    Part 2
    --- 004a.py     2021-12-04 14:54:18.621412650 -0800
    +++ 004b.py     2021-12-04 14:54:38.418542209 -0800
    @@ -60,9 +60,12 @@
             for board in boards:
                 board.mark(number)
     
    -        for board in boards:
    +        for board in list(boards):
                 if board.is_winner():
    -                print(number * board.sum_of_unmarked())
    -                return
    +                if len(boards) == 1:
    +                    print(number * board.sum_of_unmarked())
    +                    return
    +
    +                boards.remove(board)
     
     main()
    

    I had a nasty copy-paste bug (all(self.marked[index] for index in row) twice instead of having col in the second one) where I was checking each row twice to see if the board had won, and not checking the columns at all.

    my solution to part 1 actually got the right answer despite this, and then I had an interminable amount of head-scratching trying to figure out why I was getting the wrong answer to part 2, until I noticed that stupid little copy-paste error. and then of course it immediately worked.

    2 votes
  5. Comment on Weekly US politics news and updates thread - week of November 29 in ~news

    spit-evil-olive-tips
    Link Parent
    The Betrayal of Roe v Wade from Rebecca Traister, one of the best writers on feminism in American politics today:

    The Betrayal of Roe v Wade from Rebecca Traister, one of the best writers on feminism in American politics today:

    I understand the impulse to point fingers at individuals and factions, have myself often felt the gratification that comes from naming the bad guy responsible for a mess.

    ...

    But this impulse is itself shortsighted and self-serving, in that it allows us to evade the far more suffocating and incriminating reality: that we got to this terrifying place not just by some wrong turn made recently by one wrong person we don’t like, but by decades-long, systemic failures. The biggest and most damning of these is the failure to counter a regressive movement’s project to ensure minority rule and thus dismantle the rights and protections won by activists who labored over generations to gain them — abortion rights very much included. That failure in turn reflects a deeper one: an unwillingness to take the full humanity of women, of pregnant people, of Black and brown and poor people, seriously.

    It wasn’t four years after Roe that the Hyde Amendment — which barred the use of government insurance programs to pay for most abortions — first passed, making the purported legal right to abortion care practically nonexistent for people who relied on federal insurance programs for their health care. Over the half-century that abortion has been officially legal on a federal level, it has become ever more inaccessible to people of color, to poor people, to immigrants, to younger people, to people in rural communities and in red states, thanks to Hyde and thousands of state and local restrictions and regulations. Curtailed abortion access has made already imperiled populations ever more imperiled, all while Roe has officially stood.

    Yet this does not mean despair or accepting defeat, which would be yet another instance of giving in to short-term comfort and ease. It’s incumbent on us to not check out, to not give up, as it will be tempting to do on most days: to not evade responsibility by shifting the blame to others, but instead to face the future with the respect owed to our forebears and a crystal clear vision of who is going to be suffering right now and in the coming years. To settle into the work ahead, knowing that the answers won’t come in the form of a superhero candidate or a single election cycle, but rather in a rethinking of who’s authoritative and who’s hysterical; of who should be at the center and who should be at the margins; in staying committed through both wins and losses because people’s lives, and not just our own grievances, are at stake. We must reimagine whose lives and experiences should guide us into a future that must, now, be different from our recent past.

    6 votes
  6. Comment on Weekly coronavirus-related chat, questions, and minor updates - week of November 29 in ~health.coronavirus

    spit-evil-olive-tips
    Link
    Missouri health department found mask mandates work, but didn’t make findings public

    Missouri health department found mask mandates work, but didn’t make findings public

    The comparison showed infection rates in “masked” jurisdictions were higher than the rest of the state in the six weeks prior to the emergence of the delta variant. Case rates then fell below other regions as the surge gathered force in late May and have remained lower since that time.

    The statewide data shows that, from the end of April to the end of October, jurisdictions with mask mandates experienced an average of 15.8 cases per day for every 100,000 residents compared to 21.7 cases per day for every 100,000 residents in unmasked communities.

    Missouri is by no means an outlier in terms of lacking a statewide mask policy or discouraging local governments from creating their own; Missouri is one of six states that never implemented a statewide mask mandate during the pandemic.

    But Missouri's decision not to release public health data showing a demonstrable difference in COVID-19 infection and death in masked communities is notable and reflects the deep political polarization surrounding pandemic policies, one expert said.

    8 votes
  7. Comment on Day 3: Binary Diagnostic in ~comp.advent_of_code

    spit-evil-olive-tips
    Link Parent
    you can also use collections.Counter or the more versatile defaultdict for this. defaultdict is especially neat because of how the factory function for missing values works. you can do...

    ones_count = list([0] * str_len)

    you can also use collections.Counter or the more versatile defaultdict for this.

    defaultdict is especially neat because of how the factory function for missing values works. you can do defaultdict(int) or defaultdict(list) for example, and it looks like you're specifying the type - but really it works because int() and list() are used as functions to create missing values, so they initialize to 0 and the empty list, respectively.

    that means you can provide an arbitrary function as the factory method for missing values, so for example defaultdict(lambda: defaultdict(list)) gives you a 2-level nested dictionary where the values are lists. then you can do some_dict['foo']['bar'].append('a') or whatever without needing initialization code to make sure the the list you're appending to already exists.

    6 votes
  8. Comment on Day 3: Binary Diagnostic in ~comp.advent_of_code

    spit-evil-olive-tips
    Link
    part 1 was fairly easy. I used Python's Counter to build up a mapping of bit-position to number of 1s in that position. Part 1 from collections import Counter with open('003.txt') as file: lines =...

    part 1 was fairly easy. I used Python's Counter to build up a mapping of bit-position to number of 1s in that position.

    Part 1
    from collections import Counter
    
    with open('003.txt') as file:
        lines = file.readlines()
    
    counts = Counter()
    
    for line in lines:
        for index, char in enumerate(reversed(line.strip())):
            if char == '1':
                counts[index] += 1
    
    gamma = 0
    epsilon = 0
    for position, count in counts.items():
        if count > 0.5 * len(lines):
            gamma += 2 ** position
        else:
            epsilon += 2 ** position
    
    print(epsilon * gamma)
    

    then part 2...was ugly. I thought it was a rather steep difficulty increase for day 3.

    the biggest stumbling block I had was realizing that it wanted me to re-compute the bit "votes" after each iteration. initially I was only doing that once, at the beginning, and then re-using those results as I narrowed down the candidates.

    Part 2
    from collections import Counter
    
    
    def get_most_common(lines):
        counts = Counter()
        for line in lines:
            for index, char in enumerate(line):
                if char == '1':
                    counts[index] += 1
    
        winners = {}
        for index, count in counts.items():
            if count > 0.5 * len(lines):
                winners[index] = '1'
            elif count < 0.5 * len(lines):
                winners[index] = '0'
    
        return winners
    
    def discard_ratings(ratings, position, value):
        remainder = []
        for rating in ratings:
            if rating[position] == value:
                remainder.append(rating)
    
        return remainder
    
    def find_rating(candidates, most):
        position = 0
        while len(candidates) > 1:
            winners = get_most_common(candidates)
            winner = winners.get(position, '1')
            if not most:
                winner = '1' if winner == '0' else '0'
            candidates = discard_ratings(candidates, position, winner)
            position += 1
    
        return int(candidates[0], 2)
    
    def main():
        with open('003.txt') as file:
            lines = [line.strip() for line in file.readlines()]
    
        og_rating = find_rating(lines.copy(), True)
        co2_rating = find_rating(lines.copy(), False)
        print(og_rating * co2_rating)
    
    main()
    
    4 votes
  9. Comment on Rocket Lab unveils Neutron Rocket design in ~space

  10. Comment on Weekly US politics news and updates thread - week of November 29 in ~news

    spit-evil-olive-tips
    Link
    The End of Roe Is Coming, and It Is Coming Soon oral arguments in Dobbs v Jackson Women's Health were yesterday. full transcript if anyone is a glutton for punishment. the ruling likely won't come...

    The End of Roe Is Coming, and It Is Coming Soon

    After hearing arguments, I now believe that the justices will fully overturn Roe v. Wade when their decision comes down next year.

    oral arguments in Dobbs v Jackson Women's Health were yesterday. full transcript if anyone is a glutton for punishment.

    the ruling likely won't come out until June of 2022, but it seems very likely that Roe v Wade & Planned Parenthood v Casey will be overturned and there will be no federally-recognized right to an abortion in the US. due to trigger laws this means roughly 20 states will make all abortion illegal immediately.

    7 votes
  11. Comment on Day 2: Dive! in ~comp.advent_of_code

    spit-evil-olive-tips
    Link
    Part 1 with open('002.txt') as file: lines = file.readlines() position, depth = 0, 0 for line in lines: action, amount = line.split(' ') amount = int(amount) if action == 'forward': position +=...
    Part 1
    with open('002.txt') as file:
        lines = file.readlines()
    
    position, depth = 0, 0
    
    for line in lines:
        action, amount = line.split(' ')
        amount = int(amount)
        if action == 'forward':
            position += amount
        elif action == 'up':
            depth -= amount
        elif action == 'down':
            depth += amount
        else:
            raise ValueError(action)
    
    print(position * depth)
    
    Part 2
    with open('002.txt') as file:
        lines = file.readlines()
    
    position, depth = 0, 0
    aim = 0
    
    for line in lines:
        action, amount = line.split(' ')
        amount = int(amount)
        if action == 'forward':
            position += amount
            depth += (amount * aim)
        elif action == 'up':
            aim -= amount
        elif action == 'down':
            aim += amount
        else:
            raise ValueError(action)
    
    print(position * depth)
    
    diff
    --- 002a.py     2021-12-01 21:07:33.382776564 -0800
    +++ 002b.py     2021-12-01 21:08:25.628144136 -0800
    @@ -2,16 +2,18 @@
         lines = file.readlines()
     
     position, depth = 0, 0
    +aim = 0
     
     for line in lines:
         action, amount = line.split(' ')
         amount = int(amount)
         if action == 'forward':
             position += amount
    +        depth += (amount * aim)
         elif action == 'up':
    -        depth -= amount
    +        aim -= amount
         elif action == 'down':
    -        depth += amount
    +        aim += amount
         else:
             raise ValueError(action)
     
    
    4 votes
  12. Comment on Day 1: Sonar Sweep in ~comp.advent_of_code

    spit-evil-olive-tips
    Link
    fun with zip in Python Part 1 with open('001.txt') as file: lines = file.readlines() numbers = [int(line) for line in lines] increments = 0 for prev, cur in zip(numbers, numbers[1:]): if cur >...

    fun with zip in Python

    Part 1
    with open('001.txt') as file:
        lines = file.readlines()
    
    numbers = [int(line) for line in lines]
    
    increments = 0
    
    for prev, cur in zip(numbers, numbers[1:]):
        if cur > prev:
            increments += 1
    
    print(increments)
    
    Part 2
    with open('001.txt') as file:
        lines = file.readlines()
    
    numbers = [int(line) for line in lines]
    
    increments = 0
    
    windows = list(zip(numbers, numbers[1:], numbers[2:]))
    
    for prev, cur in zip(windows, windows[1:]):
        if sum(cur) > sum(prev):
            increments += 1
    
    print(increments)
    
    4 votes
  13. Comment on A group of crypto enthusiasts named Krause House DAO are raising money to buy an NBA team in ~tech

    spit-evil-olive-tips
    Link
    previous discussion of the attempt to buy a copy of the US Constitution by another DAO as I said in that thread, we've gone from speedrunning the reasons banking regulations exist to speedrunning...

    previous discussion of the attempt to buy a copy of the US Constitution by another DAO

    as I said in that thread, we've gone from speedrunning the reasons banking regulations exist to speedrunning the reasons corporate governance exists.

    the article says they've raised $4 million out of an estimated $1.3 billion necessary to buy the cheapest NBA team, the Memphis Grizzlies. so it's a long way off, but let's give them the benefit of the doubt, and suppose they can raise sufficient money to buy a team. what next?

    do they hire & fire the head coach and general manager via DAO voting? how much autonomy do those people have over the rest of the front office staff? (in the worst case, is every single employment decision the team makes put to a vote of the token-holders?)

    the entire problem seems to be that people like DAOs because they're decentralized and off in some magical web3 world disconnected from everything else...but they also want DAOs that control real-world artifacts, like a copy of the Constitution or a basketball team.

    at a certain point you no longer have "oh it's all smart contracts" accompanied by furious handwaving. eventually you get down to, there's a guy, and he's looking at a computer, and reading the results of some "binding" vote taken by the DAO. and he's supposed to go then take the real-world action decided by the DAO. and he might decide to, just...not.

    and is there any recourse? do the investors in the DAO even know the name of this guy who's supposed to carry out these real world actions dictated by the "smart contracts"? can you take him to court (in what country / jurisdiction?), and try to convince a 70 year old judge that he had some sort of fiduciary responsibility to follow the vote of the DAO? good luck with that.

    14 votes
  14. Comment on 2021 Tesla Model Y review: Nearly great, critically flawed in ~tech

    spit-evil-olive-tips
    Link
    the cruise control is broken to the point of being unsafe oh, and water leaks in if you take it through the car wash (and presumably in heavy rain too) it's a $70k car with downsides that I'd...

    The big issue is false positives, a problem that has become known as "phantom braking" among Tesla owners. Basically, the car often gets confused and thinks there's an obstacle ahead and engages the automatic emergency braking system. You get an instant, unwanted and often strong application of the brakes. This is not a problem unique to Teslas. I've experienced it on other cars, but very, very rarely. On our Model Y this happens constantly, at least once an hour and sometimes much more often than that. In a single hour of driving I caught five phantom braking incidents on camera, two hard enough to sound the automatic emergency braking chime.

    This is a massive problem. It happens on both the highway and on secondary roads, any time the cruise control is engaged even without Autosteer. It means the car's cruise control is patently unsafe, which means the entirety of Autopilot is unsafe. And that means the car itself is unsafe.

    Phantom braking is the most egregious issue I've had with our Model Y, but it isn't the only one. After running the thing through the car wash ahead of filming the review video, I popped the frunk to find a good amount of water had gathered within. Definitely don't store anything you need to keep dry.

    the cruise control is broken to the point of being unsafe

    oh, and water leaks in if you take it through the car wash (and presumably in heavy rain too)

    it's a $70k car with downsides that I'd expect if I was buying a 30 year old beater off Craigslist

    9 votes
  15. Comment on Weekly coronavirus-related chat, questions, and minor updates - week of November 22 in ~health.coronavirus

    spit-evil-olive-tips
    Link Parent
    yeah, "natural immunity" as an alternative to vaccination has been a really pernicious anti-vax talking point. (also, just calling it "natural" immunity is I think extremely misleading / very...

    yeah, "natural immunity" as an alternative to vaccination has been a really pernicious anti-vax talking point.

    (also, just calling it "natural" immunity is I think extremely misleading / very effective branding - if you catch covid, are kept alive in the hospital by a ventilator and a pile of drugs and various other artificial methods, once you get discharged from the hospital you supposedly have "natural" immunity)

    however strong someone's post-infection immunity is, being vaccinated plus having post-infection immunity will be stronger. so these studies comparing "is post-infection immunity comparable to vaccine-generated immunity?" really only serve to benefit people who want to wriggle their way out of just getting vaccinated.

    how long SARS-CoV-2 immunity lasts is an interesting epidemiological question...but for the purposes of planning out when people should get vaccine boosters. not as an excuse for people to skip getting vaccinated at all.

    the other thing none of these anti-vax (or "i'M nOt aNTI-vAx I'm juSt aNTI-ManDATe") people talk about with regards to "natural" immunity is that if you want 1 million people to have post-infection immunity, you need to infect 1 million + X people, where X is the number of people who will die as a result of 1 million covid infections. if the fatality rate is 1%, you've killed 10,000 people. if the rate is 0.1%, congrats, you've killed "only" 1000 people.

    suppose, hypothetically, post-infection immunity was equal to vaccine immunity, and there was scientific consensus on that. it wouldn't matter, because you still have all those deaths (as well as long COVID and other sequelae) as a side effect of your "natural" immunity.

    early on in the pandemic, we had the "just let everyone catch covid" crap, eventually formalized into the Great Barrington Declaration. the push for "natural immunity" as a replacement for vaccines is just the updated version of that.

    7 votes
  16. Comment on Weekly coronavirus-related chat, questions, and minor updates - week of November 22 in ~health.coronavirus

    spit-evil-olive-tips
    Link
    Exemptions for sale: How a central Washington doctor helped workers dodge vaccine mandate

    Exemptions for sale: How a central Washington doctor helped workers dodge vaccine mandate

    A three-month KING 5 investigation found Elperin repeatedly signed and sold those mask and COVID vaccine exemptions to residents across Washington state, in some cases with no questions asked. The doctor wrote exemptions for patients who did not provide a legitimate medical reason to receive one, including people who sought to evade local and state pandemic-related mandates. Charging each patient from $150 to $200 for the forms, Elperin potentially raked in tens of thousands of dollars from medical exemption sales a month and profited from state, local and private company policies intended to reduce the spread of coronavirus.

    “About 90% of Dr. Elperin’s patients every day were COVID exemption patients,” Jamison said. “Anyone off the street could get it. There was no medical history reviewed….It was just like, ‘Here’s a piece of paper.’”

    Elperin signed 20% of all exemptions filed at Ellensburg’s largest employer, Central Washington University, where proof of vaccination is now required for all students and employees. About one of every five of the 85 vaccine and mask exemptions submitted by the university’s students and staff came from Awake Health, according to public records.

    3 votes