Skip to content

Commit 43ea571

Browse files
authoredOct 1, 2023
Add files via upload
1 parent 4bf2919 commit 43ea571

14 files changed

+16813
-0
lines changed
 

‎Z/zipf-curve/README.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
To run this code, install:
2+
- `pip install -r requirements.txt`
3+
- The `texts` folder already exists if you want to use it.

‎Z/zipf-curve/requirements.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
numpy
2+
matplotlib
3+
scipy
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,371 @@
1+
# Calculator with tkinter
2+
**How to make a simple calculator with tkinter which has a history function and variable insertion.**
3+
4+
## Idea
5+
In this tutorial, we are going to make a calculator with Tkinter the built-in GUI Library in python. We are going to make a 3 by 3 Grid with buttons that represent the possible inputs, a live result showing system, a history of calculations feature, and variable insertion.
6+
7+
So let's get right into it.
8+
9+
## Imports
10+
As always we start with the imports. Because we make the UI with tkinter we need to import it, we import everything from `tkinter` so we don't have to write less code later on. We also import the font module from tkinter so we can change the fonts on our elements later.
11+
12+
We continue by getting the `partial` function from `functools`. This is a genius function that excepts another function as a first argument and some args and kwargs and it will return a reference to this function with those arguments. This is especially useful when we want to insert one of our functions to a command argument of a button or a key binding.
13+
14+
In the next line, we import `ctypes`, which allows us to enable high dpi, making our window look way sharper. This is done with the function call in the last line of this sections code block.
15+
16+
Because we'll save our history in a JSON file we import the `json` module to parse json and stringify lists.
17+
18+
We also need `re` the built-in regex module for our variable insertion feature.
19+
20+
Last but not least we get math, but we do not don't need it we just import it so it can be used in the line edit of the calculator.
21+
22+
```python
23+
from tkinter import *
24+
import tkinter.font as font
25+
from functools import partial
26+
import ctypes
27+
import json
28+
import re
29+
30+
# so the functions that can be used from the math module can be used in the line edit.
31+
import math
32+
33+
ctypes.windll.shcore.SetProcessDpiAwareness(1)
34+
```
35+
36+
## Variables and tkinter setup
37+
38+
Next up we make some variables and we set up the tkinter.
39+
40+
The first two variables are just colors for our buttons and for the background of the history panel.
41+
42+
Next, we set up tkinter by calling its Tk class and saving this object in the `root` variable. We then set the window dimensions with the `geometry()` method and the window title with `title()`.
43+
44+
We then import an image from our directory which we can set to be the icon of our program.
45+
46+
Last but not least we import the font `Consolas` in the size 12. We do this with the `Font` class from the font module of tkinter.
47+
48+
```python
49+
# Colors
50+
buttonColor = (255, 255, 255)
51+
historyPanelBackground = (255, 255, 255)
52+
53+
# Tkinter Setup
54+
root = Tk()
55+
root.geometry("550x270")
56+
root.title("Calculator")
57+
58+
# Setting icon for the Application
59+
photo = PhotoImage(file = "icon.png")
60+
root.iconphoto(False, photo)
61+
62+
# Loading Font from font name
63+
myFont = font.Font(family='Consolas', size=12)
64+
```
65+
66+
## Formulas and variable insertions
67+
68+
Now I am going to explain the variable insertion feature or at least I will try to! So the idea is that we can have a space after our equations where we declare variables that are inserted into the equation by placeholders. Let us look at this in a concrete example. If we type text below into the line edit.
69+
70+
```
71+
{a} * {b} ? a=7 & b=3
72+
```
73+
74+
... should net us this result ...
75+
76+
```
77+
21
78+
```
79+
... because where `a` was the 7 will be placed and where the `b` is we will insert the 3 and after that the equation will be evaluated and this will be `21`.
80+
81+
We will later look at how this is done in practice.
82+
83+
Below we also have a list of formulas that can be inserted into the line edit. We will make them pickable from a Menu.
84+
85+
```python
86+
# Formula Templates
87+
formulas = [
88+
['Pythagoras->c', '(({a}**2)+({b}**2))**0.5 ? a=5 & b=5'],
89+
['Pythagoras->c**2', '({a}**2)+({b}**2) ? a=5 & b=5'],
90+
['pq->(x1, x2)', '-({p}/2) + sqrt(({p}/2)**2 - ({q})), -({p}/2) - sqrt(({p}/2)**2 - ({q})) ? p=-1 & q=-12'],
91+
['abc->(x1, x2)', 'quadratic_formula({a}, {b}, {c}) ? a=1 & b=5 & c=6'],
92+
['Incline->y', '{m}{x} + {q} ? m=4 & x=5 & q=6'],
93+
]
94+
```
95+
96+
## History setup
97+
98+
Next, we set up the history feature.
99+
100+
We start by declaring a list that will hold our history items. Then we have a variable that holds the location of the `history.json` file.
101+
102+
In the end, we have a try and except block, where there is an attempt to make the file at the specified location. This is just done so the file exists in all cases.
103+
104+
```python
105+
# All the history equations are in this list.
106+
history = []
107+
108+
# Where the history file is located.
109+
historyFilePath = 'history.json'
110+
111+
print("Reading history from: ",historyFilePath )
112+
113+
# Creating History file if it does not exist.
114+
try:
115+
with open(historyFilePath, 'x') as fp:
116+
pass
117+
print("Created file at:", historyFilePath)
118+
except:
119+
print('File already exists')
120+
```
121+
122+
## RGB to hex and math function.
123+
124+
Now we talk about two functions that hold only minor importance.
125+
126+
The first one simply converts RGB colors to hex colors because tkinter only allows color names and hex colors.
127+
128+
The second one is a custom math function that can be used in the line edit.
129+
130+
```python
131+
# converting RGB values to HEX
132+
def rgb_to_hex(rgb):
133+
return "#%02x%02x%02x" % rgb
134+
135+
def quadratic_formula(a, b, c):
136+
disc = b**2 - 4 * a * c
137+
138+
x1 = (-b - math.sqrt(disc)) / (2 * a)
139+
x2 = (-b + math.sqrt(disc)) / (2 * a)
140+
141+
return(x1, x2)
142+
```
143+
144+
## Helper functions
145+
146+
Now we will go over the several helper functions that are needed to make the program work.
147+
148+
### `addSymbol`
149+
150+
This function will be called from the buttons to insert operators like `*` or `+` and numbers into the line edit. That's where the symbol parameter comes in. Now if the symbol is `<` we won't append it, we will shorten the current input. We actually change the String Variable which holds the current input.
151+
152+
```python
153+
# Add something to the current calculation
154+
def addSymbol(event=None, symbol=None):
155+
156+
if symbol == '<':
157+
entryVariable.set(entryVariable.get()[:-1])
158+
else:
159+
entryVariable.set(entryVariable.get()+symbol)
160+
```
161+
162+
### `varChange`
163+
164+
This function will be connected to change events on the input variable. In this function, we will also evaluate the equation and insert it into the result label.
165+
166+
Earlier we took a look at how the variable insertion feature functioned and now we look at how we do this in practice.
167+
168+
As you see we first split the input string by the `?` and then we save this to the `evaluationString` variable.
169+
170+
After that, we check if the input string split by `?` would result in a list with two items. If that's the case we know that there are insertion variables. Then we get this side of the string and we loop over another splitted version of this where the separator is `&`. There we modify the `evaluationString` with these variables.
171+
172+
In either case, we will try to insert the evaluated value into the result label. Now it could be that this doesn't work because the input is invalid so we cover that case.
173+
174+
```python
175+
def varChange(*args):
176+
evaluationString = entryVariable.get().replace(' ', '').split('?')[0]
177+
178+
print('Before insertion: ',evaluationString)
179+
180+
if len(entryVariable.get().split('?')) == 2:
181+
182+
parameters = entryVariable.get().replace(' ', '').split('?')[1]
183+
184+
for param in parameters.split('&'):
185+
where, what = param.split('=')
186+
evaluationString = re.sub('{'+where+'}', what, evaluationString)
187+
188+
try:
189+
print('After insertion: ', evaluationString)
190+
resultLabel.config(text=str(eval(evaluationString)))
191+
except:
192+
resultLabel.config(text='Invalid Input')
193+
```
194+
195+
### `saveCurrentInputToHistory`
196+
197+
This function simply saves the current line edit input to the history file. We first check if the value is already in the list so we don't have duplicates. We then save the history list to the history file. Here we use the `json.dump()` function. and in the end, we call the `updateListBox` function, which will be explained later.
198+
199+
```python
200+
def saveCurrentInputToHistory(event=None):
201+
if entryVariable.get() in history:
202+
return
203+
204+
history.append(entryVariable.get())
205+
206+
with open(historyFilePath, 'w') as file:
207+
file.write(json.dumps(history))
208+
209+
updateListBox()
210+
```
211+
212+
### `updateListBox`
213+
214+
This function will delete all the contents of the history list and display them again, that's why need the history variable here. We then delete all the stuff in the list with the `delete(start, end)` method. Then we get open the history file and get the json from there. And in the end, we loop over the history list and insert those values into the history list.
215+
216+
```python
217+
def updateListBox(event=None):
218+
global history
219+
220+
historyList.delete(0, END)
221+
222+
try:
223+
with open(historyFilePath, 'r') as file:
224+
history = json.loads(file.read())
225+
except json.decoder.JSONDecodeError:
226+
print('File does not contain JSON')
227+
228+
for index, item in enumerate(history):
229+
historyList.insert(index, item)
230+
```
231+
232+
### `setEntryFromHistory` and `addFormula`
233+
234+
These two functions have simple jobs.
235+
236+
The `setEntryFromHistory` enables us to click on a list item and this item will then be inserted into the line edit.
237+
238+
The `addFormula` function will do the same just for the formulas chosen from the dropdownmenu.
239+
240+
```python
241+
def setEntryFromHistory(event=None):
242+
historyItem = historyList.get(historyList.curselection()[0])
243+
entryVariable.set(historyItem)
244+
245+
def addFormula(formula=''):
246+
saveCurrentInputToHistory()
247+
entryVariable.set(formula)
248+
```
249+
250+
## UI
251+
252+
Now we will make the UI. I wont go into detail to much. There are some different to take away from the code.
253+
254+
The layout is done with the `pack` method of all widgets, and make the two-column setup by using `Frame`'s
255+
256+
```python
257+
# Work with Frames to split the window in two parts: the calculator and the History Panel.
258+
259+
# Calculation Panel
260+
calcSide = Frame(root)
261+
calcSide.pack(side=LEFT, fill=BOTH, expand=1)
262+
263+
# Entry Variable for the calculations
264+
entryVariable = StringVar(root, '4/2**2')
265+
entryVariable.trace('w', varChange)
266+
267+
Entry(calcSide, textvariable=entryVariable, font=myFont, borderwidth=0).pack(fill=X, ipady=10, ipadx=10)
268+
resultLabel = Label(calcSide, text='Result', font=myFont, borderwidth=0,anchor="e")
269+
resultLabel.pack(fill=X, ipady=10)
270+
271+
# History Panel
272+
historySide = Frame(root, bg=rgb_to_hex(historyPanelBackground))
273+
historySide.pack(side=LEFT, fill=BOTH, expand=1)
274+
275+
historyTopBar = Frame(historySide)
276+
historyTopBar.pack(fill=X)
277+
Label(historyTopBar, text='History').pack(side=LEFT)
278+
Button(historyTopBar, text='Save Current Input', bg=rgb_to_hex(buttonColor), borderwidth=0, command=saveCurrentInputToHistory).pack(side=RIGHT)
279+
280+
historyList = Listbox(historySide, borderwidth=0)
281+
historyList.pack(fill=BOTH, expand=True)
282+
historyList.bind("<Double-Button-1>", setEntryFromHistory)
283+
```
284+
285+
We also call this function so the list updates on startup.
286+
```python
287+
# Insert stuff into the history
288+
updateListBox()
289+
```
290+
Below you see how the Buttons are made. We first define a list with other lists in it where the symbols on the button are layed out.
291+
292+
Then we loop over this first list and make a new frame for each row. we continue by looping over these inner lists and generating buttons with the given symbols.
293+
294+
We set the background color on these buttons to our button color and then we lower every number from the button color tuple, this will give us a nice gradient for the buttons.
295+
296+
```python
297+
# Button Symbols (and their position)
298+
symbols = [
299+
['1', '2', '3', '+'],
300+
['4', '5', '6', '-'],
301+
['7', '8', '9', '/'],
302+
['0', '.', '<', '*'],
303+
]
304+
305+
for rowList in symbols:
306+
307+
# Make a row
308+
row = Frame(calcSide)
309+
row.pack(fill=BOTH, expand=True)
310+
for symbol in rowList:
311+
312+
# Making and packing the Button
313+
Button(
314+
row,
315+
text=symbol,
316+
command=partial(addSymbol, symbol=symbol),
317+
font=myFont,
318+
bg=rgb_to_hex(buttonColor),
319+
borderwidth=0
320+
).pack(
321+
side=LEFT,
322+
fill=BOTH,
323+
expand=1
324+
)
325+
326+
# Change button color each iteration for gradient.
327+
buttonColor = (buttonColor[0] - 10, buttonColor[1] - 10, buttonColor[1] - 2)
328+
```
329+
330+
We also make a menu where we have all our formulas ready to be inserted.
331+
332+
```python
333+
menubar = Menu(root)
334+
335+
filemenu = Menu(menubar, tearoff=0)
336+
337+
# Add all Formulas to the dropdown menu.
338+
for formula in formulas:
339+
filemenu.add_command(label=formula[0], command=partial(addFormula, formula[1]))
340+
341+
filemenu.add_separator()
342+
343+
# Quit command
344+
filemenu.add_command(label="Exit", command=root.quit)
345+
346+
menubar.add_cascade(menu=filemenu, label='Formulas')
347+
348+
root.config(menu=menubar)
349+
```
350+
351+
Now, in the end, we call the `valueChange` function so the input is evaluated on startup and we call the `mainloop()` method.
352+
353+
```python
354+
# Call the var change once so it is evaluated without actual change.
355+
varChange('foo')
356+
357+
root.mainloop()
358+
```
359+
360+
## Showcase
361+
362+
Below you see a little showcase of how the calculator works.
363+
364+
![enter image description here](https://raw.githubusercontent.com/Maximinodotpy/calculator/main/showcase%20%282%29.gif)
365+
366+
## Conclusion
367+
368+
Excellent! You have successfully created a calculator using Python code! See how you can add more features to this program such as more formulas or a converter for different things like inches to centimers
369+
## Conclusion
370+
371+
Excellent! You have successfully created a **...** using Python code! See how you can add more features to this program such as **...** .

‎Z/zipf-curve/texts/Harry Potter and the Sorcerer's Stone.txt

+10,702
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
# Password Generator with Python
2+
**How to make a password generator with python and its modules argparse and random**
3+
4+
## Idea
5+
In this tutorial, we will make a Command-line tool for generating passwords. We will use the argparse module to make it easier to parse the command line arguments the user has provided. We make it so the user can define the letters which should be included, how many passwords should be created and if they shall be saved to a .txt file.
6+
7+
Let us get started.
8+
9+
## Imports
10+
Let us import some Modules. For this program, we just need the `ArgumentParser` Class from `argparse` and the `shuffle()` and `choice()` functions from `random`. We also get the `string` module, which has some letters and numbers collections. We don't have to install any of these because they come with python.
11+
12+
```python
13+
from argparse import ArgumentParser
14+
from random import shuffle, choice
15+
import string
16+
```
17+
18+
## Setting up the argument parser.
19+
20+
Now we continue with setting up the argument parser. To do this we sav,e a new instance of the `ArgumentParser` class to our `parser` variable. We give the parser a name and a description. This information will appear if the user provides the `-h` argument when running our program, it will also tell them the possible arguments.
21+
22+
```python
23+
# Setting up the Argument Parser
24+
parser = ArgumentParser(
25+
prog='Password Generator.',
26+
description='Generate any number of passwords with this tool.'
27+
)
28+
```
29+
30+
We continue by adding arguments to the parser. The first four will be the amounts of each character type. That's why we set them all to 2 by default. We check if they are of type integer.
31+
32+
```python
33+
# Adding the arguments to the parser
34+
parser.add_argument('-numNumbers', default=2, type=int)
35+
parser.add_argument('-numLowercaseLetters', default=2, type=int)
36+
parser.add_argument('-numCapitalLetters', default=2, type=int)
37+
parser.add_argument('-numSpecialChars', default=2, type=int)
38+
```
39+
40+
The subsequent two arguments are the desired length and the number of passwords. We set the length to be eight by default because most platforms have this requirement. We check for the length and amount if it is of type int because a string or float would not make sense in this case. The store argument is a flag that just tells the program whether to store the passwords in a text file or not. By default, this is false that is why the action is `"store_true"`.
41+
42+
```python
43+
# The amount is a number so we check it to be of type int.
44+
parser.add_argument('-amount', default=1, type=int)
45+
parser.add_argument('-store', default=False, action='store_true')
46+
```
47+
48+
Last but not least we parse the command line for these arguments with the `parse_args()` method of the `ArgumentParser` class. If we don't call this method the parser won't check for anything and won't raise any exceptions.
49+
50+
```python
51+
# Parsing the command line arguments.
52+
arguments = parser.parse_args()
53+
```
54+
55+
## The Password Loop
56+
57+
We continue with the main part of the program: the Password loop. Here we generate the number of passwords specified by the user.
58+
59+
That is why we define a passwords list that will hold all the generated passwords. We don't need the number which is returned by the range generator.
60+
61+
```python
62+
passwords = []
63+
64+
# Looping through the number of passwords.
65+
for _ in range(int(arguments.amount)):
66+
```
67+
68+
After that, we make a password list which will first hold all the possible letters and then the password string.
69+
70+
```python
71+
password = []
72+
```
73+
74+
Now we add the possible letters, numbers, and special characters to the password list. For each of the types, we check if it is true in the namespace of the parser. We get the respective letters from the string module.
75+
76+
```python
77+
# If / how many Numbers the password should contain
78+
for _ in range(arguments.numNumbers):
79+
password.append(choice(string.digits))
80+
81+
# If / how many Capital Characters the password should contain
82+
for _ in range(arguments.numCapitalLetters):
83+
password.append(choice(string.ascii_uppercase))
84+
85+
# If / how many lowercase Characters the password should contain
86+
for _ in range(arguments.numLowercaseLetters):
87+
password.append(choice(string.ascii_lowercase))
88+
89+
# If / how many Special Characters the password should contain
90+
for _ in range(arguments.numSpecialChars):
91+
password.append(choice(string.punctuation))
92+
```
93+
94+
Then we use the `shuffle` function from `random` to mix up the list. This is done in place.
95+
96+
```python
97+
# Shuffle the list with all the possible letters, numbers, and symbols.
98+
shuffle(password)
99+
```
100+
101+
After this, we get the first items of the list until the length specified by the user and then we join the resulting with `""` so we have the string version of it.
102+
103+
```python
104+
# Get the letters of the string up to the length argument and then join them.
105+
password = ''.join(password)
106+
```
107+
108+
Last but not least we append this password to the passwords list.
109+
110+
```python
111+
# Append this password to the overall list of passwords.
112+
passwords.append(password)
113+
```
114+
115+
## Saving the Passwords
116+
117+
After the password loop, we check if the user said he or she wanted to save the passwords to a file. if that is the case we simply open a file, which will be made if it does not exist.
118+
119+
```python
120+
# Store the password to a .txt file.
121+
if arguments.store:
122+
with open('passwords.txt', 'w') as f:
123+
f.write('\n'.join(passwords))
124+
```
125+
126+
In all cases, we print out the passwords.
127+
128+
```python
129+
print('\n'.join(passwords))
130+
```
131+
132+
133+
## Examples
134+
135+
Now you will see some useful examples of the generator. Keep in mind this will be different for you.
136+
137+
```
138+
C:\Users\Maxim> main.py
139+
^G~0,NU4
140+
```
141+
```
142+
C:\Users\Maxim> main.py -amount 5
143+
j@BJk#IO
144+
F~§!]G_E
145+
nGg#MAW-
146+
fh=5c)-§
147+
cjFPy?]A
148+
```
149+
```
150+
C:\Users\Maxim> main.py -amount 2
151+
1*~G^n%K
152+
2ouVq)ç¬
153+
```
154+
```
155+
C:\Users\Maxim> main.py -numCapitalLetters 6
156+
O1AdJ]FQmR&7
157+
```
158+
## Imports
159+
160+
## Setting up the argument parser.
161+
162+
## Specifying the possible characters.
163+
164+
**show trick to speed up process**
165+
166+
## The Password Loop
167+
168+
## Saving the Passwords
169+
170+
## Conclusion
171+
172+
Excellent! You have successfully created a Password Generator using Python code! See how you can add more features to this program such as hashing the passwords or more options.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
# Planet Simulation with Python and Pygame
2+
**How to make a planet-class with python and its game-making module pygame.**
3+
4+
## Idea
5+
In this tutorial, we are going to make a little planet simulation with python and the game-making library pygame. Pygame has a handy vector class that can help us when simulating the planets and their heading.
6+
7+
So let us start with the imports.
8+
9+
## Imports
10+
11+
All of the modules we import are built-in except the pygame library, which we have to install with `pip install pygame`. We also need `sys`, but it will simply be used to stop the game when pressing on the x at the top left of the window. After that, we get the `Vector2` class from `pygame.math`. It offers some interesting methods to use when we want to work with vectors. The `randrange()` function from random will just be used when we make some planets. We also get `ctypes` to enable high DPI. This is often used with `tkinter` but we can also use it here, even though it has not as great an effect.
12+
13+
```python
14+
# Imports
15+
import pygame
16+
import sys
17+
18+
# We will work with Vector2 because it has some useful functions.
19+
from pygame.math import Vector2
20+
21+
from random import randrange
22+
23+
import ctypes
24+
25+
# Enable High Dots Per Inch so the image displayed on the window is sharper.
26+
ctypes.windll.shcore.SetProcessDpiAwareness(1)
27+
```
28+
29+
## Pygame Setup
30+
31+
Next, we set up pygame, to do this we start with `pygame.init()` this has to be called so all the modules work. After that, we define the game's fps and we make a clock object which will handle the game speed in combination with the defined fps.
32+
33+
```python
34+
# Configuration
35+
pygame.init()
36+
fps = 60
37+
fpsClock = pygame.time.Clock()
38+
```
39+
40+
We continue by defining the window size and making the window with these sizes.
41+
42+
```python
43+
# Window Size
44+
windowdim = Vector2(800, 800)
45+
screen = pygame.display.set_mode((int(windowdim.x), int(windowdim.y)))
46+
```
47+
48+
## Planet Class
49+
Let us get into the planet-class this is the main part of this program's code because it allows us to make an infinite amount of planets that will react to each other.
50+
51+
Outside of the class we just need to define a list that holds all of the planets. Then in the main loop, we loop over this list and call a method on all of these objects.
52+
53+
```python
54+
# all the Planets are stored here
55+
# They will append themselves.
56+
planets = []
57+
```
58+
59+
### Constructor Function
60+
61+
Let us first talk about the constructor of the class. We provide each planet with a starting position and we have the following optional arguments; delta, which is the velocity, the radius of the planet, and if the planet is immovable. We set all of these inputs to a variable available to the class.
62+
63+
```python
64+
# The Planet Class which will handle drawing and calculating planets.
65+
class Planet():
66+
def __init__(self, position, delta=Vector2(0, 0), radius=10, imovable=False):
67+
68+
# Where the planet is at the moment
69+
self.position = position
70+
71+
# The Radius determines how much this planet affects others
72+
self.radius = radius
73+
74+
# The Velocity
75+
self.delta = delta
76+
77+
# If this planet is moving
78+
self.imovable = imovable
79+
80+
# If this planet can be eaten by others.
81+
self.eatable = False
82+
```
83+
84+
At the end of the constructor, we append the object itself to the planet list so we don't have to do this manually.
85+
86+
```python
87+
# Appending itself to the list so its process
88+
# function will later be called in a loop.
89+
planets.append(self)
90+
```
91+
92+
### Process Function
93+
94+
Let us talk about the process function. This will be called for each planet in each frame. The whole of the movement code will be skipped if the `imovable` property is set to True. If the planet can move it will loop through every other planet and if the planet is not the object itself we continue.
95+
96+
If the planet is too near to this one it will be eaten this is done by adding the radius of this planet to the other one and removing this planet from the list.
97+
98+
If that's, not the case we calculate the vector to the other planet and then we add it to the delta. Now, this whole code is in a try-except block because it won't work if the planets are on top of each other. After that, we add the delta to the position.
99+
100+
```python
101+
# This function will be called once every frame
102+
# and it is responsible for calculating where the planet will go.
103+
104+
# No Movement Calculations will happen if the planet doesn't move at all.
105+
# it also won't be eaten.
106+
if not-self.imovable:
107+
for i in planets:
108+
109+
if not i is self:
110+
try:
111+
if self.eatable:
112+
if self.position.distance_to(i.position) < self.radius + i.radius:
113+
print('Eaten')
114+
115+
i.radius += self.radius
116+
117+
planets.remove(self)
118+
119+
dir_from_obj = (i.position - self.position).normalize() * 0.01 * (i.radius / 10)
120+
self.delta += dir_from_obj
121+
122+
except:
123+
print('In the same spot')
124+
125+
self.position += self.delta
126+
```
127+
128+
In the end, we draw the planet at its position this is done even if the planet is immovable.
129+
130+
```python
131+
# Drawing the planet at the current position.
132+
pygame.draw.circle(
133+
screen,
134+
[255, 255, 255],
135+
self.position,
136+
self.radius,
137+
)
138+
```
139+
140+
## Main Loop
141+
142+
Last but not least we have the mainloop which will cool the process function on each planet in the planets list every frame.
143+
144+
```python
145+
# Game loop.
146+
while True:
147+
screen.fill((0, 0, 0))
148+
for event in pygame.event.get():
149+
if event.type == pygame.QUIT:
150+
pygame.quit()
151+
sys.exit()
152+
153+
for p in planets:
154+
p.process()
155+
156+
pygame.display.flip()
157+
fpsClock.tick(fps)
158+
```
159+
160+
Now, this code won't spawn planets by itself. In the next part, we look at some examples.
161+
162+
## Examples
163+
164+
### Sun and two opposing Planets
165+
166+
This code is run right before the main loop. and it will spawn three planets. After the code, you see it in action.
167+
168+
```python
169+
# Sun and two opposing Planets
170+
Planet(Vector2(400, 400), radius=50, imovable=True)
171+
172+
Planet(Vector2(400, 200), delta=Vector2(3, 0), radius=10)
173+
Planet(Vector2(400, 600), delta=Vector2(-3, 0), radius=10)
174+
```
175+
176+
![enter image description here](https://maximmaeder.com/wp-content/uploads/2022/06/p1.gif)
177+
178+
### Sun and four opposing Planets
179+
180+
```python
181+
# Sun and four opposing Planets
182+
Planet(Vector2(400, 400), radius=50, imovable=True)
183+
184+
Planet(Vector2(400, 200), delta=Vector2(3, 0), radius=10)
185+
Planet(Vector2(400, 600), delta=Vector2(-3, 0), radius=10)
186+
Planet(Vector2(600, 400), delta=Vector2(0, 3), radius=10)
187+
Planet(Vector2(200, 400), delta=Vector2(0, -3), radius=10)
188+
```
189+
190+
![enter image description here](https://maximmaeder.com/wp-content/uploads/2022/06/p2.gif)
191+
192+
### Two Suns and two planets
193+
194+
```python
195+
# Two Suns and two planets
196+
Planet(Vector2(600, 400), radius=20, imovable=True)
197+
Planet(Vector2(200, 400), radius=20, imovable=True)
198+
199+
Planet(Vector2(400, 200), delta=Vector2(0, 0), radius=10)
200+
Planet(Vector2(400, 210), delta=Vector2(1, 2), radius=5)
201+
```
202+
203+
![enter image description here](https://maximmaeder.com/wp-content/uploads/2022/06/p3.gif)
204+
205+
### Grid
206+
207+
```python
208+
# Grid
209+
gridDimension = 10
210+
gridgap = 80
211+
for x in range(gridDimension):
212+
for y in range(gridDimension):
213+
Planet(Vector2(gridgap * x + 40, gridgap * y + 40), radius=3, imovable=True)
214+
215+
Planet(Vector2(200, 200), delta=Vector2(randrange(-3, 3), 2), radius=5)
216+
```
217+
218+
![enter image description here](https://maximmaeder.com/wp-content/uploads/2022/06/p4.gif)
219+
220+
## Conclusion
221+
222+
Excellent! You have successfully created a Planet Simulation using Python code! See how you can add more features to this program such as a UI to place planets or more settings for the planets.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
# Simple Text editor with Tkinter.
2+
**How to make a simple program capable of opening, editing, and saving text files.**
3+
4+
## Idea
5+
We are going to make a simple text editor with the Tkinter module which comes with python so we don't have to install anything. It will have the following features.
6+
- Open text files.
7+
- Edit text files.
8+
- Save text files.
9+
- Open With (our Editor)
10+
11+
## Imports
12+
We start by importing some Modules which we all later need. We import Everything from `Tkinter` so we have all the variables available and we also import the `scrolledText` and `filedialog` classes individually. The Scrolled text will be the Text Area where we write and the file dialog allows us to trigger the `askfileopen` window.
13+
14+
```python
15+
# Import
16+
from tkinter import *
17+
from tkinter import scrolledtext
18+
from tkinter import filedialog
19+
```
20+
21+
Next, we import ctypes to enable high DPI (Dots per inch) so our window looks sharper. Below the Code, you will find a comparison.
22+
23+
```python
24+
import ctypes
25+
```
26+
**Low DPI**
27+
![enter image description here](https://i.imgur.com/hOyvTtq.png)
28+
29+
**High DPI**
30+
![enter image description here](https://i.imgur.com/Z6MPMFD.png)
31+
32+
Last but not least we import `sys` so we can analyze the arguments given through the command line. We later use this to enable *open with*.
33+
34+
```python
35+
import sys
36+
```
37+
38+
## Variable Setup
39+
Now we set up some variables for our little program. The first two variables are used to keep consistency when titling our program. The `currentFilePath` is used when saving the file so we know where to save it. This String will also be appended to the window title like many programs do to show what file is being edited. At last, we define which file types can be opened with our editor. We used this variable in the file dialogues.
40+
41+
```python
42+
# Setup Variables
43+
appName = 'Simple Text Editor'
44+
nofileOpenedString = 'New File'
45+
46+
currentFilePath = nofileOpenedString
47+
48+
# Viable File Types, when opening and saving files.
49+
fileTypes = [("Text Files","*.txt"), ("Markdown","*.md")]
50+
```
51+
52+
## Tkinter Setup
53+
Next, we are going to set up the Tkinter window. To do that we make a new `Tk` object. After that, we give the window a title, and we use the variables we defined earlier. Because we have no file opened at the moment it will say `Simple Text Editor - New File`. We will also make it so an asterisk will be added in front of the file name so we know when we have unsaved changes. Then we set the initial window Dimensions in pixels with the `geometry` method of tkinter. Last but not least we set the first column to take up 100% of the space so our text area will be the full width.
54+
55+
```python
56+
# Tkinter Setup
57+
window = Tk()
58+
59+
window.title(appName + " - " + currentFilePath)
60+
61+
# Window Dimensions in Pixel
62+
window.geometry('500x400')
63+
64+
# Set the first column to occupy 100% of the width
65+
window.grid_columnconfigure(0, weight=1)
66+
```
67+
68+
## Handler Functions
69+
Now we are going to set up two functions that are connected to some events called by tkiner widgets.
70+
71+
### File Actions
72+
The first function is called when we press any of the file buttons so we can save open and make new files. Later you will see how we connect them. We have to get the `currentFilePath` because it was defined outside this function. Our function will take one argument namely the action, which defines what we want to do. We will check for this argument and do stuff dependent on that.
73+
74+
So if the action is `open` we will trigger an `askopenfilename` through the dialog class. We supply it with the filetypes we defined earlier so the user will only be able open these file types. After we chose the file, the function will return the path of the file. Then we set the Window Title to our `appName - File Path`. After that, we set our `currentFilePath` to this file path. Now we just open the file and insert the content into our text area called `txt` after we cleared it with the `delete` method.
75+
76+
```python
77+
# Handler Functions
78+
def fileDropDownHandeler(action):
79+
global currentFilePath
80+
81+
# Opening a File
82+
if action == "open":
83+
file = filedialog.askopenfilename(filetypes = fileTypes)
84+
85+
window.title(appName + " - " + file)
86+
87+
currentFilePath = file
88+
89+
with open(file, 'r') as f:
90+
txt.delete(1.0,END)
91+
txt.insert(INSERT,f.read())
92+
```
93+
94+
If the action is `new` we will set the file path to `New File`. Then we also delete the text in the text area and we reset the window title.
95+
96+
```python
97+
# Making a new File
98+
elif action == "new":
99+
currentFilePath = nofileOpenedString
100+
txt.delete(1.0,END)
101+
window.title(appName + " - " + currentFilePath)
102+
```
103+
Last but not least we will check for `save` or `saveAs`. Now if the file is new or we pressed the Save As button we will ask the user where he wants to save the file. Then we open the file and save the text from the text area there. After that, we reset the window title because there probably was an asterisk.
104+
```python
105+
# Saving a file
106+
elif action == "save" or action == "saveAs":
107+
if currentFilePath == nofileOpenedString or action=='saveAs':
108+
currentFilePath = filedialog.asksaveasfilename(filetypes = fileTypes)
109+
110+
with open(currentFilePath, 'w') as f:
111+
f.write(txt.get('1.0','end'))
112+
113+
window.title(appName + " - " + currentFilePath)
114+
```
115+
116+
### Text Change
117+
Now for a simple function. Whenever the text area is changed well call this function to simply add an asterisk in from of the current file Path to show the user that there are unsaved changes.
118+
119+
```python
120+
def textchange(event):
121+
window.title(appName + " - *" + currentFilePath)
122+
```
123+
124+
## Widgets
125+
Now we are going to set up the Graphical Elements.
126+
127+
### Text Area
128+
129+
First, we set up the Text Area and set its height to 999 so it spans the full height. then we set its position through the `grid` method. `sticky=N+S+E+W` to tell the widget to grow in all directions when the user resizes the window. with the bind method, we say that whenever a key is pressed in the text area we call the `textchange` function.
130+
131+
```python
132+
# Text Area
133+
txt = scrolledtext.ScrolledText(window, height=999)
134+
txt.grid(row=1,sticky=N+S+E+W)
135+
136+
# Bind event in the widget to a function
137+
txt.bind('<KeyPress>', textchange)
138+
```
139+
140+
### Menu
141+
142+
Now set up our Dropdown menu for file interactions. We first make a new `Menu` which has the root window. Then we make a second one that has the root of the first menu. We set the `tearoff` to false so the user won't be able to `tearoff` this menu to have it as a separate window.
143+
144+
Then we add commands to this menu with its `add_command` method. We have to supply this function with a label that represents the displayed text and a command which is then called function if the button is pressed. We need to make a `lambda` which calls our `fileDropDownHandler` function. We have to do this so we can supply our function with an argument. We can also add separators with the `add_seperator` method. In the end, we add this menu as a cascade to the menu button and we set this menu to be the main menu.
145+
146+
```python
147+
# Menu
148+
menu = Menu(window)
149+
150+
# set tearoff to 0
151+
fileDropdown = Menu(menu, tearoff=False)
152+
153+
# Add Commands and and their callbacks
154+
fileDropdown.add_command(label='New', command=lambda: fileDropDownHandeler("new"))
155+
fileDropdown.add_command(label='Open', command=lambda: fileDropDownHandeler("open"))
156+
157+
# Adding a seperator between button types.
158+
fileDropdown.add_separator()
159+
fileDropdown.add_command(label='Save', command=lambda: fileDropDownHandeler("save"))
160+
fileDropdown.add_command(label='Save as', command=lambda: fileDropDownHandeler("saveAs"))
161+
162+
menu.add_cascade(label='File', menu=fileDropdown)
163+
164+
# Set Menu to be Main Menu
165+
window.config(menu=menu)
166+
```
167+
168+
## Open with
169+
170+
Now we enable the user to open a file directly with our program with this little code snippet. We check if the system argument length equates to two we know that the second argument is the path of the desired file. So we now set the `currentFilePath` to this path. After that, we do essentially the same as with the open with handler function.
171+
172+
```python
173+
# Enabling "open with" by looking if the second argument was passed.
174+
if len(sys.argv) == 2:
175+
currentFilePath = sys.argv[1]
176+
177+
window.title(appName + " - " + currentFilePath)
178+
179+
with open(currentFilePath, 'r') as f:
180+
txt.delete(1.0,END)
181+
txt.insert(INSERT,f.read())
182+
```
183+
184+
## Main Loop
185+
In the end we also call the main loop method on the window so the window even displays. Without this, it would not work.
186+
187+
```python
188+
# Main Loop
189+
window.mainloop()
190+
```
191+
192+
## Showcase
193+
194+
Now you will see how the program works in a short gif.
195+
![enter image description here](https://i.imgur.com/hsKSEg4.gif)m capable of opening, editing and saving text files.**
196+
197+
## Idea
198+
199+
## Imports
200+
201+
202+
```python
203+
pass
204+
```

‎Z/zipf-curve/wordamounts.png

226 KB
Unable to render code block

‎Z/zipf-curve/zipf_curve.py

+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# Imports
2+
import os
3+
from matplotlib import pyplot as plt
4+
import string
5+
import numpy as np
6+
from scipy.interpolate import make_interp_spline
7+
8+
# define some dictionaries
9+
texts = {}
10+
textlengths = {}
11+
textwordamounts = {}
12+
13+
unwantedCharacters = list(string.punctuation)
14+
15+
# How many ranks well show
16+
depth = 10
17+
xAxis = [str(number) for number in range(1, depth+1)]
18+
19+
# Getting all files in text folder
20+
filePaths = os.listdir('texts')
21+
22+
# Getting text from .txt files in folder
23+
for path in filePaths:
24+
with open(os.path.join('texts', path), 'r', encoding='UTF-8') as f:
25+
texts[path.split('.')[0]] = f.read()
26+
27+
28+
# Cleaning and counting the Text
29+
for text in texts:
30+
# Remove unwanted characters from the texts
31+
for character in unwantedCharacters:
32+
texts[text] = texts[text].replace(character, '').lower()
33+
34+
splittedText = texts[text].split(' ')
35+
36+
# Saving the text length to show in the label of the line later
37+
textlengths[text] = len(splittedText)
38+
39+
# Here will be the amount of occurence of each word stored
40+
textwordamounts[text] = {}
41+
42+
# Loop through all words in the text
43+
for i in splittedText:
44+
45+
# Add to the word at the given position if it already exists
46+
# Else set the amount to one essentially making a new item in the dict
47+
if i in textwordamounts[text].keys():
48+
textwordamounts[text][i] += 1
49+
else:
50+
textwordamounts[text][i] = 1
51+
52+
# Sorting the dict by the values with sorted
53+
# define custom key so the function knows what to use when sorting
54+
textwordamounts[text] = dict(
55+
sorted(
56+
textwordamounts[text ].items(),
57+
key=lambda x: x[1],
58+
reverse=True)[0:depth]
59+
)
60+
61+
# Get the percentage value of a given max value
62+
def percentify(value, max):
63+
return round(value / max * 100)
64+
65+
# Generate smooth curvess
66+
def smoothify(yInput):
67+
68+
x = np.array(range(0, depth))
69+
y = np.array(yInput)
70+
71+
# define x as 600 equally spaced values between the min and max of original x
72+
x_smooth = np.linspace(x.min(), x.max(), 600)
73+
74+
# define spline with degree k=3, which determines the amount of wiggle
75+
spl = make_interp_spline(x, y, k=3)
76+
y_smooth = spl(x_smooth)
77+
78+
# Return the twe x and y axis
79+
return x_smooth, y_smooth
80+
81+
# Make the perfect Curve
82+
ziffianCurveValues = [100/i for i in range(1, depth+1)]
83+
84+
x, y = smoothify(ziffianCurveValues)
85+
86+
plt.plot(x, y, label='Ziffian Curve', ls=':', color='grey')
87+
88+
89+
# Plot the texts
90+
for i in textwordamounts:
91+
maxValue = list(textwordamounts[i].values())[0]
92+
93+
yAxis = [percentify(value, maxValue) for value in list(textwordamounts[i].values())]
94+
95+
x, y = smoothify(yAxis)
96+
97+
plt.plot(x, y, label=i+f' [{textlengths[i]}]', lw=1, alpha=0.5)
98+
99+
plt.xticks(range(0, depth), xAxis)
100+
101+
plt.legend()
102+
plt.savefig('wordamounts.png', dpi=300)
103+
plt.show()

‎Z/zipfile-cracker/README.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# To run this:
2+
- `pip3 install -r requirements.txt`
3+
- Cracking `secret.zip` file with the password list in `wordlist.txt` file, use the following command:
4+
```
5+
python zip_cracker.py secret.zip wordlist.txt
6+
```
7+
- For a bigger list, consider downloading [rockyou](https://github.com/brannondorsey/naive-hashcat/releases/download/data/rockyou.txt) wordlist.

‎Z/zipfile-cracker/requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
tqdm

‎Z/zipfile-cracker/secret.zip

20.1 KB
Binary file not shown.

‎Z/zipfile-cracker/wordlist.txt

+5,000
Large diffs are not rendered by default.

‎Z/zipfile-cracker/zip_cracker.py

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from tqdm import tqdm
2+
3+
import zipfile
4+
import sys
5+
6+
# the password list path you want to use
7+
wordlist = sys.argv[2]
8+
# the zip file you want to crack its password
9+
zip_file = sys.argv[1]
10+
# initialize the Zip File object
11+
zip_file = zipfile.ZipFile(zip_file)
12+
# count the number of words in this wordlist
13+
n_words = len(list(open(wordlist, "rb")))
14+
# print the total number of passwords
15+
print("Total passwords to test:", n_words)
16+
with open(wordlist, "rb") as wordlist:
17+
for word in tqdm(wordlist, total=n_words, unit="word"):
18+
try:
19+
zip_file.extractall(pwd=word.strip())
20+
except:
21+
continue
22+
else:
23+
print("[+] Password found:", word.decode().strip())
24+
exit(0)
25+
print("[!] Password not found, try other wordlist.")

0 commit comments

Comments
 (0)
Please sign in to comment.