TrickJarrett.com

Posts Tagged: python

A delightful journey in programming

I am reminded what a giant nerd I am since I watched this while working on other very nerdy things.

Share to: | Tags: python, programming

Podcast Middleman Dev

Hammered the majority of the podcast middleman out this morning thanks to Python. A few things still to fix (like the fact The Daily has a 12.5 meg RSS file and I am not looking to archive their entire backlog) but the core functionality is there and it's just about trimming off what I don't locally archive, etc.

Share to: | Tags: programming, python, project

Never Stop Blowing Up's Dice System

So I decided to do some math & coding this morning. I was curious on the distribution of numbers for the exploding dice system used in Dropout's new actual play series: Never Stop Blowing Up

They are using a system built on the Kids on Bikes system, modified to serve the game's theming. The main difference (based on what we've seen) is the dice rolling system.

For Kids on Bikes, you roll the same die when it explodes. For Never Stop, you start with a D4, then on a max roll, you roll again on the next sized dice (D4->D6->D8->D10->D12->D20) adding the combined values of rolls. Roll 1, 2, 3 that's what you get, on a 4, you add 1d6, etc

There's a few more details to what Never Stop is doing, like that it makes it quasi-leveling for the players. Once you explode to a d6, that is now your starting dice roll on that stat, etc. I'm not taking that into consideration for this morning's exploration on the math.

So, looking at every roll beginning with a D4, you have a 25% chance on rolling 1, 2 or 3. Then the remaining 25% chance gets distributed across exploding rolls.

% Range
25% 1-3
4.17% 5-9
0.52% 11-17
0.05% 19-27
0.04% 29-39
0.002% 41-60

You can never roll a 4, 10 (4+6), 18 (4+6+8), 28 (4+6+8+10), 40 (4...12) because those are the threshold numbers an you always add at least 1 to those numbers. This essentially means that everything after these thresholds uses that slot's percentage.

So with 1d4, you have a 25% chance of getting a 4. But since there is no 4, the remaining range of numbers all occupy that 25%. Adding the 1d6 means that you have 25%/6 on each possible roll, except on a 6, that is the percentile chance of the 1d8, etc.

So that's the part I logicked through the math of without any code or simulation. I decided to code a Python script to do large number simulations to see how many times I would roll each number.

from random import randint

dice = [4, 6, 8, 10, 12, 20]

def roll(sides):
    r = randint(1,sides)
    if r == sides and r < 20:
        n = dice.index(sides) + 1
        return r + roll(dice[n])
    return r

def batchroll():
    rolls = []

    for i in range(10000):
        rolls.append(roll(4))

    out = ""
    for i in range(1,61):
        out = out + str(rolls.count(i)) + "\t"

    out = out + "\n"

    with open("rolls.txt", "a") as text_file:
        text_file.write(out)

for x in range(10000):
    batchroll()

(Don't judge the code, I'm sure it could be improved.)

First off, after running it - I was glad to see that I had logicked it all out correctly and the rolls matched expectations. Secondly, seeing actual distribution of numbers was useful for perspective. It's one thing to see them as abstract percentiles, but it's another to see actual numbers of instances.

Out of nearly 100 million simulated rolls, I only rolled on the d20 ~4,300 times. Meaning that with 100,000,000 rolls; I rolled the max of "60" (4+6+...+20) just 203 times. Here's the results of the simulated rolls on a Google Sheet.

Interesting stuff mathematically. A fun morning exercise for the ol' noggin.

Share to: | Tags: dice, python, programming, math

Update on last night's 'Wikindle' code

Code ran without issue, though the formatting was slightly off.

This morning I hammered out the code to grab the top 100 most popular entries from yesterday and add them to the archive. I'm not sure how useful that will actually be, a lot of those entries are pop culture (am I really going to need an entry about the new Kraven Marvel series?) But we'll see. It isn't like this is a major space hog.

Last night snagged roughly 8,000 entries and it took up 250 megs. Plenty of space.

One thing which is lost in this process is any cross linking. I'd love to go through and add that back in, or even better figure out how to best avoid that bring stripped out from the start. We'll see. In any case, a fun diversion to distract me.

Share to: | Tags: programming, project, wikipedia, python

Wikipedia on my Shelf Progress

At this moment my PC is downloading nearly 10,000 entries from Wikipedia as part of my idea of a locally hosted version of the encyclopedia. I'm making use of the Vital articles project, specifically level 4, which is roughly ten thousand entries on various topics.

I cobbled together a python script to pull from the API, parse the HTML to markdown, strip any lingering tags (such as spans, abbrs, etc.)

It isn't perfect, no images from the entries are brought over. I'll work on that further in a future iteration.

Not sure what to call this project. I called the folder "Wikindle" as a smerging of "wikipedia" and "kindle" but I don't love that name. I'll play around with it.

I also have an idea for this to be a "living" archive. Where perhaps it is a cron script which runs nightly for that day's top X entries, and snags them, accruing more and more notable content over time. Obviously quality will vary, but we'll see how it goes. Then, every few months, I update the Kindle.

Lastly, my observation as I work on code this evening. It remains comforting that ChatGPT struggles with some very basic coding concepts. I know lots of people worry LLMs will lead to the end of programmers but that simply isn't true as far as I can see. At least, not without more massive steps forward.

Share to: | Tags: programming, project, wikipedia, python

Coding ChatGPT from Scratch

Absolutely loving this step by step walk through explaining the terminology and how exactly it all works.

Share to: | Tags: programming, python, machine learning

Python spelling correction deep dive

Ran across this old article about how Google does their spelling correction on searches. You search for 'speling' and they say 'Returning results for 'spelling'' - It's a bit of a deep dive for anyone who isn't proficient with programming.

Share to: | Tags: programming, python

Ran an update on my "ToListen" script this morning. This is the code from last week which turns a YT playlist into an MP3 podcast. In the words of Marie Kondo, it sparks joy.

Share to: | Tags: python, programming, youtube, podcast

It's Alive!

After roughly three hours of coding I have a 130 line Python script that will snag the videos on my "To Watch" YouTube playlist, convert the files to mp3s, generate a podcast XML file, and then upload them all to my server.

Now I can use a podcast app while I'm driving and listen to these files. I had a way of listening to them while I drove but it was a process which required me picking up and interacting with my phone, it didn't integrate with Android Auto. This script will now allow that.

This is definitely an MVP hacky solution. But, it's a hacky solution that gets the job done. As of now, I'll just run it from my laptop. No need to set this up on the server as an automated script. The frequency is such that I add 1-3 videos to the list in a week. Right now it has 19 videos on it. So plenty of backlog and I can probably just do it as a weekly task and I'll be fine.

Also, jeez, I forget how easy Python is to work in. I do the majority of my web coding in PHP, but it was nice to lean heavily on the existing Python libraries for this one.

Share to: | Tags: programming, python

I continue my efforts to learn Python, tonight's project was to implement a calendar function. Python has a built in tool that does this, but it's about learning the language and implementing the tools for it. I was able to do it in about 60 minutes, with most of that being troubleshooting errors and learning some of the requirements for Python.

As I come from PHP, getting used to strict typing on variables is a big learning for me.

One of the common pitfalls I fall into is naming my files an obvious filename, which ends up being also something I import. For example, tonight's file was originally called 'calendar.py' but since I am importing the calendar library in python, it was erroring. So it got renamed to cal.py.

Here's the code I came up with:

import calendar
from datetime import datetime

date = input("Enter Date: ")

dt = datetime.strptime(date,"%m/%d/%Y")

header = datetime.strftime(dt,"%B %Y")

weekday = int(datetime.strftime(dt,"%w"))
date = int(datetime.strftime(dt,"%-d"))

month = int(datetime.strftime(dt,"%-m"))
year = int(datetime.strftime(dt,"%Y"))
firstDateOfMonth = int(datetime.strftime(datetime.strptime(str(month)+"/1/"+str(year),"%m/%d/%Y"),"%w"))

lengthOfMonth = int(calendar.monthrange(int(year),int(month))[1])

print(header)
print("[Sun][Mon][Tue][Wed][Thu][Fri][Sat]")

line = ""

if firstDateOfMonth > 0:
    k = 0
    while k  6:
        print(line)
        line = ""
        k = 0
    filler = " "
    if i == date:
        filler = "*"
    if i This code outputs a simple text calendar such as the following:
Share to: | Tags: learning, python, programming

Python online Textbook

Now that I've gotten a few Python projects under my belt by process of code segments and rough guesses, I figured it was time I give a book a read and learn what else Python holds in store for me.

Share to: | Tags: programming, python

Simple Tic-Tac-Toe in Python

My learning of Python continued today with me coding a simple Tic-Tac-Toe client. It is very dumb, the computer always plays randomly and currently has no intelligence to it. But I wrote it from scratch with no outside resource or code segments. Doing things like this is always a great feeling for me, learning something is one of my favorite things to do.

Here is my Python code:

from random import randint

board = [1,2,3,4,5,6,7,8,9]
legalplays = [1,2,3,4,5,6,7,8,9]

def drawboard(board):
   print(board[0],"|",board[1],"|",board[2])
   print("---------")
   print(board[3],"|",board[4],"|",board[5])
   print("---------")
   print(board[6],"|",board[7],"|",board[8])


def checkboard(board):
   patterns = [[0,1,2],
               [3,4,5],
               [6,7,8],
               [0,3,6],
               [1,4,7],
               [2,5,8],
               [0,4,8],
               [2,4,6]]
   for pattern in patterns:
       if board[pattern[0]] == board[pattern[1]] and board[pattern[0]] == board[pattern[2]]:
           return board[pattern[0]]
   return 0


def computerPlay(board):
   availableplays = []
   for i in board:
       if i in legalplays:
           availableplays.append(i-1);
   moves = len(availableplays)
   move = randint(0,moves-1)
   return availableplays[move]


playfirst = randint(1,2)

if playfirst == 1:
   #Computer Plays First
   play = randint(0,8)
   board[play] = "O";

noresult = True

while noresult:
   drawboard(board)
   player = input("Choose where to put your X: ")

   if player.isnumeric():
       player = int(player) - 1
       if player 
Share to: | Tags: programming, python

I am working on learning Python as a programming language and getting used to it. I sat down and coded "Rock, Scissors, Paper, Lizard, Spock" - First I did the endless if, elif, else statements then decided to go for a more compact solution via a dense multidimensional array.

from random import randint

t = [["Rock",[0,-1,1,1,-1],["ties","is covered by","smashes","crushes","is thrown by"]],
   ["Paper",[1,0,-1,-1,1],["covers","ties","is cut by","is eaten by","disproves"]],
   ["Scissors",[-1,1,0,1,-1],["smashed by","cuts","ties","decapitates","is used by"]],
   ["Lizard",[-1,1,-1,0,1],["is crushed by","eats","is decapitated by","ties","poisons"]],
   ["Spock",[1,-1,1,-1,0],["throws","is disproven by","uses","is poisoned by","ties"]]]

#assing a random play to computer
computerindex = randint(0,4)

player = False;

while player == False:
   player = input("Rock, Paper, Scissors, Lizard, Spock? ")

   noresult = True
   for entry in t:
       if entry[0] == player:
           if entry[1][computerindex] > 0:
               noresult = False
               print("You win! ",player,entry[2][computerindex],t[computerindex][0])
           elif entry[1][computerindex] 
Share to: | Tags: python, programming