millerlib 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of millerlib might be problematic. Click here for more details.
- millerlib-1.0.0/PKG-INFO +22 -0
- millerlib-1.0.0/README.md +5 -0
- millerlib-1.0.0/miller_lib/__init__.py +331 -0
- millerlib-1.0.0/millerlib.egg-info/PKG-INFO +22 -0
- millerlib-1.0.0/millerlib.egg-info/SOURCES.txt +7 -0
- millerlib-1.0.0/millerlib.egg-info/dependency_links.txt +1 -0
- millerlib-1.0.0/millerlib.egg-info/top_level.txt +1 -0
- millerlib-1.0.0/setup.cfg +4 -0
- millerlib-1.0.0/setup.py +17 -0
millerlib-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: millerlib
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Набор CLI и GUI утилит: таблицы истинности, системы счисления, битовые сдвиги
|
|
5
|
+
Author: Твое Имя/Никнейм
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Requires-Python: >=3.6
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
Dynamic: author
|
|
12
|
+
Dynamic: classifier
|
|
13
|
+
Dynamic: description
|
|
14
|
+
Dynamic: description-content-type
|
|
15
|
+
Dynamic: requires-python
|
|
16
|
+
Dynamic: summary
|
|
17
|
+
|
|
18
|
+
Запустить приложение:
|
|
19
|
+
|
|
20
|
+
launch_app_ui() - запуск CLI программы
|
|
21
|
+
|
|
22
|
+
launch_app_gui() - запуск GUI программы
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
from time import sleep
|
|
2
|
+
import tkinter as tk
|
|
3
|
+
from tkinter import messagebox, simpledialog
|
|
4
|
+
|
|
5
|
+
# ==========================================
|
|
6
|
+
# 1. СИСТЕМЫ СЧИСЛЕНИЯ (Логика)
|
|
7
|
+
# ==========================================
|
|
8
|
+
class BaseConverter:
|
|
9
|
+
def __init__(self, alphabet="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"):
|
|
10
|
+
self.letters = alphabet
|
|
11
|
+
|
|
12
|
+
def to_10(self, number, base):
|
|
13
|
+
a = str(number).upper()
|
|
14
|
+
dec = 0
|
|
15
|
+
for i in range(len(a)):
|
|
16
|
+
dec += (self.letters.find(a[i])) * base**(len(a)-i-1)
|
|
17
|
+
return dec
|
|
18
|
+
|
|
19
|
+
def from_10(self, number, base):
|
|
20
|
+
a = int(number)
|
|
21
|
+
if a == 0: return self.letters[0]
|
|
22
|
+
k = ""
|
|
23
|
+
while a > 0:
|
|
24
|
+
k = k + self.letters[a % base]
|
|
25
|
+
a //= base
|
|
26
|
+
return k[::-1]
|
|
27
|
+
|
|
28
|
+
def base_to_base(self, number, base, to_base):
|
|
29
|
+
a = self.to_10(number, base)
|
|
30
|
+
return self.from_10(a, to_base)
|
|
31
|
+
|
|
32
|
+
# ==========================================
|
|
33
|
+
# 2. УМНОЖЕНИЕ БИТОВЫМ СДВИГОМ (Логика)
|
|
34
|
+
# ==========================================
|
|
35
|
+
def bitwise_multiply(a, b):
|
|
36
|
+
result = 0
|
|
37
|
+
steps = []
|
|
38
|
+
abs_a, abs_b = abs(a), abs(b)
|
|
39
|
+
steps.append(f"Умножаем {abs_a} на {abs_b} битовым сдвигом:")
|
|
40
|
+
|
|
41
|
+
while abs_b > 0:
|
|
42
|
+
step_info = f"[A={abs_a:<4} | B={abs_b:<4}] Младший бит B: {abs_b & 1}"
|
|
43
|
+
if abs_b & 1:
|
|
44
|
+
result += abs_a
|
|
45
|
+
step_info += f" -> Прибавляем A. (Сумма: {result})"
|
|
46
|
+
else:
|
|
47
|
+
step_info += f" -> Пропускаем."
|
|
48
|
+
|
|
49
|
+
steps.append(step_info)
|
|
50
|
+
abs_a <<= 1
|
|
51
|
+
abs_b >>= 1
|
|
52
|
+
|
|
53
|
+
if (a < 0 and b > 0) or (a > 0 and b < 0):
|
|
54
|
+
result = -result
|
|
55
|
+
return result, steps
|
|
56
|
+
|
|
57
|
+
# ==========================================
|
|
58
|
+
# 3. ТАБЛИЦА ИСТИННОСТИ (Логика)
|
|
59
|
+
# ==========================================
|
|
60
|
+
english_alphabet = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
|
|
61
|
+
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
|
|
62
|
+
|
|
63
|
+
PREC = {"not": 5, "and": 4, "xor": 3, "or": 2, "->": 1, "=": 0}
|
|
64
|
+
RIGHT = {"not", "->", "="}
|
|
65
|
+
|
|
66
|
+
SYMB = {
|
|
67
|
+
"+": "or", "or": "or", "*": "and", "and": "and",
|
|
68
|
+
"xor": "xor", "XOR": "xor", "!=": "xor",
|
|
69
|
+
"not": "not", "->": "->", "=>": "->", "=": "=", "==": "="
|
|
70
|
+
}
|
|
71
|
+
DISPLAY_SYM = {"and": "*", "or": "+", "xor": "xor", "->": "->", "=": "="}
|
|
72
|
+
|
|
73
|
+
def apply_op(op, a, b=None):
|
|
74
|
+
if op == "not": return not a
|
|
75
|
+
if op == "and": return a and b
|
|
76
|
+
if op == "or": return a or b
|
|
77
|
+
if op == "xor": return a != b
|
|
78
|
+
if op == "->": return (not a) or b
|
|
79
|
+
if op == "=": return a == b
|
|
80
|
+
raise ValueError("Неизвестный оператор: " + str(op))
|
|
81
|
+
|
|
82
|
+
def remove_outer_brackets(s):
|
|
83
|
+
if not (s.startswith("(") and s.endswith(")")): return s
|
|
84
|
+
depth = 0
|
|
85
|
+
for i in range(len(s)):
|
|
86
|
+
if s[i] == "(": depth += 1
|
|
87
|
+
elif s[i] == ")": depth -= 1
|
|
88
|
+
if depth == 0 and i < len(s) - 1: return s
|
|
89
|
+
return s[1:-1]
|
|
90
|
+
|
|
91
|
+
def prettify(name):
|
|
92
|
+
name = remove_outer_brackets(name)
|
|
93
|
+
changed = True
|
|
94
|
+
while changed:
|
|
95
|
+
changed = False
|
|
96
|
+
new_name = ""
|
|
97
|
+
i = 0
|
|
98
|
+
while i < len(name):
|
|
99
|
+
if name.startswith("(not ", i):
|
|
100
|
+
j = name.find(")", i)
|
|
101
|
+
if j != -1:
|
|
102
|
+
inner = name[i + 5:j]
|
|
103
|
+
if " " not in inner and "(" not in inner and ")" not in inner:
|
|
104
|
+
new_name += "not " + inner
|
|
105
|
+
i = j + 1
|
|
106
|
+
changed = True
|
|
107
|
+
continue
|
|
108
|
+
new_name += name[i]
|
|
109
|
+
i += 1
|
|
110
|
+
name = new_name
|
|
111
|
+
return name
|
|
112
|
+
|
|
113
|
+
def calculate(h, params):
|
|
114
|
+
values = {p[0]: bool(p[1]) for p in params}
|
|
115
|
+
out, ops, steps = [], [], []
|
|
116
|
+
|
|
117
|
+
def apply_top():
|
|
118
|
+
op = ops.pop()
|
|
119
|
+
if op == "not":
|
|
120
|
+
name, val = out.pop()
|
|
121
|
+
new = ("(not " + name + ")", not val)
|
|
122
|
+
else:
|
|
123
|
+
b_name, b_val = out.pop()
|
|
124
|
+
a_name, a_val = out.pop()
|
|
125
|
+
new = ("(" + a_name + " " + DISPLAY_SYM[op] + " " + b_name + ")", apply_op(op, a_val, b_val))
|
|
126
|
+
out.append(new)
|
|
127
|
+
steps.append(new)
|
|
128
|
+
|
|
129
|
+
for t in h:
|
|
130
|
+
if t == "(": ops.append(t)
|
|
131
|
+
elif t == ")":
|
|
132
|
+
while ops and ops[-1] != "(": apply_top()
|
|
133
|
+
ops.pop()
|
|
134
|
+
elif t in PREC:
|
|
135
|
+
while (ops and ops[-1] != "(" and
|
|
136
|
+
(PREC[ops[-1]] > PREC[t] or (PREC[ops[-1]] == PREC[t] and t not in RIGHT))):
|
|
137
|
+
apply_top()
|
|
138
|
+
ops.append(t)
|
|
139
|
+
elif t in values: out.append((t, values[t]))
|
|
140
|
+
|
|
141
|
+
while ops: apply_top()
|
|
142
|
+
return steps
|
|
143
|
+
|
|
144
|
+
def custom_tabulate(headers, rows):
|
|
145
|
+
"""Кастомный рендер таблиц без сторонних библиотек"""
|
|
146
|
+
col_widths = [len(str(h)) for h in headers]
|
|
147
|
+
for row in rows:
|
|
148
|
+
for i, cell in enumerate(row):
|
|
149
|
+
col_widths[i] = max(col_widths[i], len(str(cell)))
|
|
150
|
+
|
|
151
|
+
separator = "+" + "+".join("-" * (w + 2) for w in col_widths) + "+"
|
|
152
|
+
lines = [separator]
|
|
153
|
+
|
|
154
|
+
header_str = "|" + "|".join(f" {str(headers[i]).center(col_widths[i])} " for i in range(len(headers))) + "|"
|
|
155
|
+
lines.append(header_str)
|
|
156
|
+
lines.append(separator)
|
|
157
|
+
|
|
158
|
+
for row in rows:
|
|
159
|
+
row_str = "|" + "|".join(f" {str(row[i]).center(col_widths[i])} " for i in range(len(row))) + "|"
|
|
160
|
+
lines.append(row_str)
|
|
161
|
+
|
|
162
|
+
lines.append(separator)
|
|
163
|
+
return "\n".join(lines)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
# ==========================================
|
|
167
|
+
# 4. КОНСОЛЬНЫЙ ИНТЕРФЕЙС (CLI)
|
|
168
|
+
# ==========================================
|
|
169
|
+
width_programm = 60
|
|
170
|
+
converter = BaseConverter()
|
|
171
|
+
|
|
172
|
+
def clear(): print("\n" * 40)
|
|
173
|
+
def group(num, symbol): print((symbol * width_programm + "\n") * (num - 1), end=""); print(symbol * width_programm)
|
|
174
|
+
def pregroup(string, space, symbol): print(symbol * max(0, (width_programm - len(string) - space * 2) // 2) + " " * space + string + " " * space + symbol * max(0, (width_programm - len(string) - space * 2) // 2))
|
|
175
|
+
def warning(text, space): group(1, "!"); pregroup(text, space, "!"); group(1, "!"); sleep(1); input("Нажмите ENTER..."); clear()
|
|
176
|
+
def print_centered(text):
|
|
177
|
+
for line in text.split("\n"): print(" " * max(0, (width_programm - len(line)) // 2) + line)
|
|
178
|
+
|
|
179
|
+
def cli_truth_table():
|
|
180
|
+
clear()
|
|
181
|
+
group(3, "-"); pregroup("ТАБЛИЦА ИСТИННОСТИ", 3, "-"); group(3, "-")
|
|
182
|
+
raw = input("Введите выражение: ").replace("(", " ( ").replace(")", " ) ")
|
|
183
|
+
tokens = raw.split()
|
|
184
|
+
a = [SYMB.get(t, t) for t in tokens]
|
|
185
|
+
params, lettersin = [], []
|
|
186
|
+
for i in english_alphabet:
|
|
187
|
+
if i in a: params.append([i, 0]); lettersin.append(i)
|
|
188
|
+
|
|
189
|
+
if not params: return warning("В выражении нет переменных!", 2)
|
|
190
|
+
|
|
191
|
+
try: steps_example = calculate(a, params)
|
|
192
|
+
except Exception as e: return warning(f"Ошибка: {e}", 2)
|
|
193
|
+
|
|
194
|
+
step_names = [prettify(name) for name, _ in steps_example]
|
|
195
|
+
columns = lettersin + step_names
|
|
196
|
+
results = [[] for _ in range(len(columns))]
|
|
197
|
+
end = False
|
|
198
|
+
|
|
199
|
+
while not end:
|
|
200
|
+
for i in range(len(params) - 1, 0, -1):
|
|
201
|
+
if params[i][1] == 2: params[i][1] = 0; params[i - 1][1] += 1
|
|
202
|
+
if params[0][1] == 2: end = True
|
|
203
|
+
else:
|
|
204
|
+
for i in range(len(params)): results[i].append(params[i][1])
|
|
205
|
+
steps = calculate(a, params)
|
|
206
|
+
for j in range(len(steps)): results[len(lettersin) + j].append(int(steps[j][1]))
|
|
207
|
+
params[-1][1] += 1
|
|
208
|
+
|
|
209
|
+
rows = list(zip(*results))
|
|
210
|
+
table_text = custom_tabulate(columns, rows)
|
|
211
|
+
|
|
212
|
+
clear()
|
|
213
|
+
group(1, "="); pregroup("Результат:", 3, "="); group(1, "=")
|
|
214
|
+
print()
|
|
215
|
+
print_centered(table_text)
|
|
216
|
+
print()
|
|
217
|
+
warning("Готово!", 3)
|
|
218
|
+
|
|
219
|
+
def launch_app_ui():
|
|
220
|
+
"""Запускает программу в режиме консоли"""
|
|
221
|
+
while True:
|
|
222
|
+
clear()
|
|
223
|
+
group(3, "="); pregroup("ГЛАВНОЕ МЕНЮ (КОНСОЛЬ)", 3, "=")
|
|
224
|
+
pregroup("1 - Таблица истинности", 3, " ")
|
|
225
|
+
pregroup("2 - Системы счисления", 3, " ")
|
|
226
|
+
pregroup("3 - Умножение битовым сдвигом", 3, " ")
|
|
227
|
+
pregroup("0 - Выход", 3, " ")
|
|
228
|
+
group(3, "=")
|
|
229
|
+
|
|
230
|
+
choice = input("Ваш выбор: ")
|
|
231
|
+
if choice == "1": cli_truth_table()
|
|
232
|
+
elif choice == "2":
|
|
233
|
+
clear()
|
|
234
|
+
try:
|
|
235
|
+
inp = input("Введите число и его базу через пробел: ").split()
|
|
236
|
+
num, base = inp[0], int(inp[1])
|
|
237
|
+
to_base = int(input("В какую базу перевести? "))
|
|
238
|
+
print(f"Результат: {converter.base_to_base(num, base, to_base)}")
|
|
239
|
+
warning("Успешно!", 1)
|
|
240
|
+
except: warning("Ошибка ввода!", 1)
|
|
241
|
+
elif choice == "3":
|
|
242
|
+
clear()
|
|
243
|
+
try:
|
|
244
|
+
a, b = int(input("Первое число: ")), int(input("Второе число: "))
|
|
245
|
+
res, steps = bitwise_multiply(a, b)
|
|
246
|
+
for step in steps: print(step); sleep(0.05)
|
|
247
|
+
print(f"\nОТВЕТ: {res}")
|
|
248
|
+
warning("Успешно!", 1)
|
|
249
|
+
except: warning("Ошибка ввода!", 1)
|
|
250
|
+
elif choice == "0": break
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
# ==========================================
|
|
254
|
+
# 5. ГРАФИЧЕСКИЙ ИНТЕРФЕЙС (GUI - Tkinter)
|
|
255
|
+
# ==========================================
|
|
256
|
+
def launch_app_gui():
|
|
257
|
+
"""Запускает программу в режиме оконного приложения (Tkinter)"""
|
|
258
|
+
root = tk.Tk()
|
|
259
|
+
root.title("Miller Tools")
|
|
260
|
+
root.geometry("400x350")
|
|
261
|
+
root.configure(bg="#2b2b2b")
|
|
262
|
+
|
|
263
|
+
def gui_base_converter():
|
|
264
|
+
num = simpledialog.askstring("Ввод", "Введите число:", parent=root)
|
|
265
|
+
if not num: return
|
|
266
|
+
base = simpledialog.askinteger("Ввод", "Система счисления числа:", parent=root)
|
|
267
|
+
to_base = simpledialog.askinteger("Ввод", "В какую систему перевести:", parent=root)
|
|
268
|
+
try:
|
|
269
|
+
res = converter.base_to_base(num, base, to_base)
|
|
270
|
+
messagebox.showinfo("Результат", f"{num} (база {base}) = {res} (база {to_base})")
|
|
271
|
+
except: messagebox.showerror("Ошибка", "Проверьте правильность ввода!")
|
|
272
|
+
|
|
273
|
+
def gui_bitwise():
|
|
274
|
+
a = simpledialog.askinteger("Ввод", "Первое число:", parent=root)
|
|
275
|
+
if a is None: return
|
|
276
|
+
b = simpledialog.askinteger("Ввод", "Второе число:", parent=root)
|
|
277
|
+
if b is None: return
|
|
278
|
+
res, steps = bitwise_multiply(a, b)
|
|
279
|
+
messagebox.showinfo("Результат", f"{a} * {b} = {res}\n\n" + "\n".join(steps))
|
|
280
|
+
|
|
281
|
+
def gui_truth_table():
|
|
282
|
+
raw = simpledialog.askstring("Ввод", "Введите выражение (например: A * B + C):", parent=root)
|
|
283
|
+
if not raw: return
|
|
284
|
+
raw = raw.replace("(", " ( ").replace(")", " ) ")
|
|
285
|
+
a = [SYMB.get(t, t) for t in raw.split()]
|
|
286
|
+
params, lettersin = [], []
|
|
287
|
+
for i in english_alphabet:
|
|
288
|
+
if i in a: params.append([i, 0]); lettersin.append(i)
|
|
289
|
+
|
|
290
|
+
if not params:
|
|
291
|
+
messagebox.showerror("Ошибка", "Нет переменных!")
|
|
292
|
+
return
|
|
293
|
+
|
|
294
|
+
try:
|
|
295
|
+
steps_example = calculate(a, params)
|
|
296
|
+
step_names = [prettify(name) for name, _ in steps_example]
|
|
297
|
+
columns = lettersin + step_names
|
|
298
|
+
results = [[] for _ in range(len(columns))]
|
|
299
|
+
end = False
|
|
300
|
+
while not end:
|
|
301
|
+
for i in range(len(params) - 1, 0, -1):
|
|
302
|
+
if params[i][1] == 2: params[i][1] = 0; params[i - 1][1] += 1
|
|
303
|
+
if params[0][1] == 2: end = True
|
|
304
|
+
else:
|
|
305
|
+
for i in range(len(params)): results[i].append(params[i][1])
|
|
306
|
+
steps = calculate(a, params)
|
|
307
|
+
for j in range(len(steps)): results[len(lettersin) + j].append(int(steps[j][1]))
|
|
308
|
+
params[-1][1] += 1
|
|
309
|
+
|
|
310
|
+
rows = list(zip(*results))
|
|
311
|
+
table_text = custom_tabulate(columns, rows)
|
|
312
|
+
|
|
313
|
+
# Открываем новое окно для таблицы
|
|
314
|
+
top = tk.Toplevel(root)
|
|
315
|
+
top.title("Таблица истинности")
|
|
316
|
+
txt = tk.Text(top, font=("Courier New", 10), wrap="none", bg="#1e1e1e", fg="#00ff00")
|
|
317
|
+
txt.insert("1.0", table_text)
|
|
318
|
+
txt.pack(expand=True, fill="both")
|
|
319
|
+
except Exception as e:
|
|
320
|
+
messagebox.showerror("Ошибка", str(e))
|
|
321
|
+
|
|
322
|
+
tk.Label(root, text="Набор утилит", font=("Courier New", 18, "bold"), bg="#2b2b2b", fg="white").pack(pady=15)
|
|
323
|
+
btn_style = {"font": ("Courier New", 11), "bg": "#4CAF50", "fg": "white", "width": 30, "pady": 5}
|
|
324
|
+
|
|
325
|
+
tk.Button(root, text="1. Таблица истинности", command=gui_truth_table, **btn_style).pack(pady=5)
|
|
326
|
+
tk.Button(root, text="2. Системы счисления", command=gui_base_converter, **btn_style).pack(pady=5)
|
|
327
|
+
tk.Button(root, text="3. Умножение сдвигом", command=gui_bitwise, **btn_style).pack(pady=5)
|
|
328
|
+
|
|
329
|
+
tk.Button(root, text="Выход", command=root.destroy, font=("Courier New", 11), bg="#d32f2f", fg="white", width=30).pack(pady=15)
|
|
330
|
+
|
|
331
|
+
root.mainloop()
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: millerlib
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Набор CLI и GUI утилит: таблицы истинности, системы счисления, битовые сдвиги
|
|
5
|
+
Author: Твое Имя/Никнейм
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Requires-Python: >=3.6
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
Dynamic: author
|
|
12
|
+
Dynamic: classifier
|
|
13
|
+
Dynamic: description
|
|
14
|
+
Dynamic: description-content-type
|
|
15
|
+
Dynamic: requires-python
|
|
16
|
+
Dynamic: summary
|
|
17
|
+
|
|
18
|
+
Запустить приложение:
|
|
19
|
+
|
|
20
|
+
launch_app_ui() - запуск CLI программы
|
|
21
|
+
|
|
22
|
+
launch_app_gui() - запуск GUI программы
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
miller_lib
|
millerlib-1.0.0/setup.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
setup(
|
|
4
|
+
name="millerlib", # Имя пакета для pip install (используй дефис вместо подчеркивания)
|
|
5
|
+
version="1.0.0",
|
|
6
|
+
author="Твое Имя/Никнейм",
|
|
7
|
+
description="Набор CLI и GUI утилит: таблицы истинности, системы счисления, битовые сдвиги",
|
|
8
|
+
long_description=open("README.md", encoding="utf-8").read(),
|
|
9
|
+
long_description_content_type="text/markdown",
|
|
10
|
+
packages=find_packages(),
|
|
11
|
+
classifiers=[
|
|
12
|
+
"Programming Language :: Python :: 3",
|
|
13
|
+
"License :: OSI Approved :: MIT License",
|
|
14
|
+
"Operating System :: OS Independent",
|
|
15
|
+
],
|
|
16
|
+
python_requires=">=3.6",
|
|
17
|
+
)
|