kececinumbers 0.1.4__tar.gz → 0.1.5__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.
- {kececinumbers-0.1.4/kececinumbers.egg-info → kececinumbers-0.1.5}/PKG-INFO +36 -1
- {kececinumbers-0.1.4 → kececinumbers-0.1.5}/README.md +35 -0
- {kececinumbers-0.1.4 → kececinumbers-0.1.5}/kececinumbers/kececinumbers.py +249 -96
- {kececinumbers-0.1.4 → kececinumbers-0.1.5/kececinumbers.egg-info}/PKG-INFO +36 -1
- {kececinumbers-0.1.4 → kececinumbers-0.1.5}/setup.py +1 -1
- {kececinumbers-0.1.4 → kececinumbers-0.1.5}/LICENSE +0 -0
- {kececinumbers-0.1.4 → kececinumbers-0.1.5}/MANIFEST.in +0 -0
- {kececinumbers-0.1.4 → kececinumbers-0.1.5}/kececinumbers/__init__.py +0 -0
- {kececinumbers-0.1.4 → kececinumbers-0.1.5}/kececinumbers/_version.py +0 -0
- {kececinumbers-0.1.4 → kececinumbers-0.1.5}/kececinumbers.egg-info/SOURCES.txt +0 -0
- {kececinumbers-0.1.4 → kececinumbers-0.1.5}/kececinumbers.egg-info/dependency_links.txt +0 -0
- {kececinumbers-0.1.4 → kececinumbers-0.1.5}/kececinumbers.egg-info/requires.txt +0 -0
- {kececinumbers-0.1.4 → kececinumbers-0.1.5}/kececinumbers.egg-info/top_level.txt +0 -0
- {kececinumbers-0.1.4 → kececinumbers-0.1.5}/pyproject.toml +0 -0
- {kececinumbers-0.1.4 → kececinumbers-0.1.5}/setup.cfg +0 -0
- {kececinumbers-0.1.4 → kececinumbers-0.1.5}/tests/test_sample.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: kececinumbers
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.5
|
4
4
|
Summary: Keçeci Numbers An Exploration of a Dynamic Sequence Across Diverse Number Sets
|
5
5
|
Home-page: https://github.com/WhiteSymmetry/kececinumbers
|
6
6
|
Author: Mehmet Keçeci
|
@@ -149,6 +149,41 @@ Enter the number of iterations (positive integer: e.g., 30): 30
|
|
149
149
|
|
150
150
|

|
151
151
|
|
152
|
+
---
|
153
|
+
# Keçeci Prime Number
|
154
|
+
|
155
|
+
```python
|
156
|
+
import matplotlib.pyplot as plt
|
157
|
+
import kececinumbers as kn
|
158
|
+
|
159
|
+
|
160
|
+
print("--- Interactive Test ---")
|
161
|
+
seq_interactive = kn.get_interactive()
|
162
|
+
if seq_interactive:
|
163
|
+
kn.plot_numbers(seq_interactive, "Keçeci Numbers")
|
164
|
+
|
165
|
+
print("\n--- Random Type Test (60 Keçeci Steps) ---")
|
166
|
+
# num_iterations burada Keçeci adımı sayısıdır
|
167
|
+
seq_random = kn.get_random_type(num_iterations=60)
|
168
|
+
if seq_random:
|
169
|
+
kn.plot_numbers(seq_random, "Random Type Keçeci Numbers")
|
170
|
+
|
171
|
+
print("\n--- Fixed Params Test (Complex, 60 Keçeci Steps) ---")
|
172
|
+
seq_fixed = kn.get_with_params(
|
173
|
+
kececi_type_choice=kn.TYPE_COMPLEX,
|
174
|
+
iterations=60,
|
175
|
+
start_value_raw="1+2j",
|
176
|
+
add_value_base_scalar=3.0
|
177
|
+
)
|
178
|
+
if seq_fixed:
|
179
|
+
kn.plot_numbers(seq_fixed, "Fixed Params (Complex) Keçeci Numbers")
|
180
|
+
|
181
|
+
# İsterseniz find_kececi_prime_number'ı ayrıca da çağırabilirsiniz:
|
182
|
+
if seq_fixed:
|
183
|
+
kpn_direct = kn.find_kececi_prime_number(seq_fixed)
|
184
|
+
if kpn_direct is not None:
|
185
|
+
print(f"\nDirect call to find_kececi_prime_number for fixed numbers: {kpn_direct}")
|
186
|
+
```
|
152
187
|
---
|
153
188
|
|
154
189
|
## License / Lisans
|
@@ -116,6 +116,41 @@ Enter the number of iterations (positive integer: e.g., 30): 30
|
|
116
116
|
|
117
117
|

|
118
118
|
|
119
|
+
---
|
120
|
+
# Keçeci Prime Number
|
121
|
+
|
122
|
+
```python
|
123
|
+
import matplotlib.pyplot as plt
|
124
|
+
import kececinumbers as kn
|
125
|
+
|
126
|
+
|
127
|
+
print("--- Interactive Test ---")
|
128
|
+
seq_interactive = kn.get_interactive()
|
129
|
+
if seq_interactive:
|
130
|
+
kn.plot_numbers(seq_interactive, "Keçeci Numbers")
|
131
|
+
|
132
|
+
print("\n--- Random Type Test (60 Keçeci Steps) ---")
|
133
|
+
# num_iterations burada Keçeci adımı sayısıdır
|
134
|
+
seq_random = kn.get_random_type(num_iterations=60)
|
135
|
+
if seq_random:
|
136
|
+
kn.plot_numbers(seq_random, "Random Type Keçeci Numbers")
|
137
|
+
|
138
|
+
print("\n--- Fixed Params Test (Complex, 60 Keçeci Steps) ---")
|
139
|
+
seq_fixed = kn.get_with_params(
|
140
|
+
kececi_type_choice=kn.TYPE_COMPLEX,
|
141
|
+
iterations=60,
|
142
|
+
start_value_raw="1+2j",
|
143
|
+
add_value_base_scalar=3.0
|
144
|
+
)
|
145
|
+
if seq_fixed:
|
146
|
+
kn.plot_numbers(seq_fixed, "Fixed Params (Complex) Keçeci Numbers")
|
147
|
+
|
148
|
+
# İsterseniz find_kececi_prime_number'ı ayrıca da çağırabilirsiniz:
|
149
|
+
if seq_fixed:
|
150
|
+
kpn_direct = kn.find_kececi_prime_number(seq_fixed)
|
151
|
+
if kpn_direct is not None:
|
152
|
+
print(f"\nDirect call to find_kececi_prime_number for fixed numbers: {kpn_direct}")
|
153
|
+
```
|
119
154
|
---
|
120
155
|
|
121
156
|
## License / Lisans
|
@@ -6,6 +6,7 @@ import numpy as np
|
|
6
6
|
import math
|
7
7
|
from fractions import Fraction
|
8
8
|
import quaternion # pip install numpy numpy-quaternion
|
9
|
+
import collections
|
9
10
|
|
10
11
|
|
11
12
|
# --- Helper Functions ---
|
@@ -33,7 +34,13 @@ def is_prime(n_input):
|
|
33
34
|
|
34
35
|
if value_to_check < 2:
|
35
36
|
return False
|
36
|
-
|
37
|
+
# Optimize for 2 and even numbers
|
38
|
+
if value_to_check == 2:
|
39
|
+
return True
|
40
|
+
if value_to_check % 2 == 0:
|
41
|
+
return False
|
42
|
+
# Check only odd divisors up to sqrt(n)
|
43
|
+
for i in range(3, int(value_to_check**0.5) + 1, 2):
|
37
44
|
if value_to_check % i == 0:
|
38
45
|
return False
|
39
46
|
return True
|
@@ -66,35 +73,24 @@ def unified_generator(kececi_type, start_input_raw, add_input_base_scalar, itera
|
|
66
73
|
ask_unit = 1
|
67
74
|
use_integer_division = True
|
68
75
|
elif kececi_type == 3: # Complex Numbers
|
69
|
-
# Adım 1: start_input_raw'ı bir complex sayıya dönüştür
|
70
76
|
if isinstance(start_input_raw, complex):
|
71
|
-
# Zaten bir complex sayı ise, doğrudan kullan
|
72
77
|
start_complex_val = start_input_raw
|
73
78
|
elif isinstance(start_input_raw, (int, float)):
|
74
|
-
# Eğer int veya float ise, s+sj yap (kullanıcının beklentisi buysa)
|
75
79
|
s_scalar = float(start_input_raw)
|
76
80
|
start_complex_val = complex(s_scalar, s_scalar)
|
77
|
-
else:
|
81
|
+
else:
|
78
82
|
try:
|
79
|
-
# Doğrudan complex sayı string'i mi diye dene (örn: "1+2j")
|
80
83
|
start_complex_val = complex(str(start_input_raw))
|
81
84
|
except ValueError:
|
82
|
-
# Eğer complex() başarısız olduysa, skaler bir sayı string'i olabilir (örn: "3")
|
83
|
-
# Bu durumda s+sj yapalım
|
84
85
|
try:
|
85
86
|
s_scalar_from_string = float(str(start_input_raw))
|
86
87
|
start_complex_val = complex(s_scalar_from_string, s_scalar_from_string)
|
87
88
|
except ValueError:
|
88
89
|
raise ValueError(f"Cannot convert start_input_raw '{start_input_raw}' to a complex number.")
|
89
|
-
|
90
90
|
current_value = start_complex_val
|
91
|
-
|
92
|
-
# Adım 2: add_input_base_scalar'dan _add_value_typed oluştur
|
93
91
|
a_scalar_for_add = float(add_input_base_scalar)
|
94
92
|
_add_value_typed = complex(a_scalar_for_add, a_scalar_for_add) # a+aj
|
95
|
-
|
96
93
|
ask_unit = 1 + 1j
|
97
|
-
# use_integer_division = False (Zaten varsayılan)
|
98
94
|
elif kececi_type == 4: # Floating-Point Numbers
|
99
95
|
current_value = float(start_input_raw)
|
100
96
|
_add_value_typed = float(add_input_base_scalar)
|
@@ -102,29 +98,33 @@ def unified_generator(kececi_type, start_input_raw, add_input_base_scalar, itera
|
|
102
98
|
elif kececi_type == 5: # Rational Numbers
|
103
99
|
if isinstance(start_input_raw, Fraction):
|
104
100
|
current_value = start_input_raw
|
105
|
-
else:
|
101
|
+
else:
|
106
102
|
current_value = Fraction(str(start_input_raw))
|
107
|
-
_add_value_typed = Fraction(str(add_input_base_scalar))
|
103
|
+
_add_value_typed = Fraction(str(add_input_base_scalar))
|
108
104
|
ask_unit = Fraction(1, 1)
|
109
105
|
elif kececi_type == 6: # Quaternions
|
110
106
|
s_val_q_raw = float(start_input_raw) if not isinstance(start_input_raw, np.quaternion) else start_input_raw
|
111
107
|
a_val_q_scalar = float(add_input_base_scalar)
|
112
108
|
if isinstance(s_val_q_raw, np.quaternion):
|
113
109
|
current_value = s_val_q_raw
|
114
|
-
else:
|
110
|
+
else:
|
115
111
|
current_value = np.quaternion(s_val_q_raw, s_val_q_raw, s_val_q_raw, s_val_q_raw)
|
116
112
|
_add_value_typed = np.quaternion(a_val_q_scalar, a_val_q_scalar, a_val_q_scalar, a_val_q_scalar)
|
117
|
-
ask_unit = np.quaternion(1, 1, 1, 1)
|
113
|
+
ask_unit = np.quaternion(1, 1, 1, 1)
|
118
114
|
else:
|
119
115
|
raise ValueError("Invalid Keçeci Number Type")
|
120
116
|
|
121
117
|
sequence.append(current_value)
|
122
|
-
last_divisor_used = None
|
123
|
-
ask_counter = 0
|
118
|
+
last_divisor_used = None
|
119
|
+
ask_counter = 0
|
124
120
|
|
125
|
-
|
121
|
+
actual_iterations_done = 0
|
122
|
+
while actual_iterations_done < iterations:
|
126
123
|
added_value = current_value + _add_value_typed
|
127
124
|
sequence.append(added_value)
|
125
|
+
actual_iterations_done += 1
|
126
|
+
if actual_iterations_done >= iterations: break
|
127
|
+
|
128
128
|
|
129
129
|
value_for_primality_check = added_value
|
130
130
|
|
@@ -139,28 +139,35 @@ def unified_generator(kececi_type, start_input_raw, add_input_base_scalar, itera
|
|
139
139
|
if kececi_type in [1, 2]:
|
140
140
|
can_divide = (added_value % divisor_candidate == 0)
|
141
141
|
elif kececi_type == 3:
|
142
|
-
can_divide = math.isclose(added_value.real % divisor_candidate, 0)
|
142
|
+
can_divide = math.isclose(added_value.real % divisor_candidate, 0) and math.isclose(added_value.imag % divisor_candidate, 0)
|
143
143
|
elif kececi_type == 4:
|
144
144
|
can_divide = math.isclose(added_value % divisor_candidate, 0) or \
|
145
|
-
math.isclose(added_value % divisor_candidate, divisor_candidate)
|
145
|
+
math.isclose(added_value % divisor_candidate, divisor_candidate) # handles floating point precision
|
146
146
|
elif kececi_type == 5:
|
147
147
|
if divisor_candidate != 0:
|
148
148
|
quotient_rational = added_value / divisor_candidate
|
149
149
|
can_divide = (quotient_rational.denominator == 1)
|
150
150
|
elif kececi_type == 6:
|
151
|
-
|
151
|
+
# For quaternions, typically division is by scalar. Check if all components are divisible.
|
152
|
+
# Or, as per your current `is_prime`, just check the scalar part.
|
153
|
+
# Let's stick to the scalar part for consistency with `is_prime` for now.
|
154
|
+
can_divide = math.isclose(added_value.w % divisor_candidate, 0) and \
|
155
|
+
math.isclose(added_value.x % divisor_candidate, 0) and \
|
156
|
+
math.isclose(added_value.y % divisor_candidate, 0) and \
|
157
|
+
math.isclose(added_value.z % divisor_candidate, 0)
|
158
|
+
|
152
159
|
|
153
160
|
if can_divide:
|
154
161
|
if use_integer_division:
|
155
162
|
result_value = added_value // divisor_candidate
|
156
163
|
else:
|
157
|
-
result_value = added_value / divisor_candidate
|
164
|
+
result_value = added_value / divisor_candidate # For complex, float, rational, quaternion
|
158
165
|
last_divisor_used = divisor_candidate
|
159
166
|
divided_successfully = True
|
160
167
|
break
|
161
168
|
|
162
169
|
if not divided_successfully:
|
163
|
-
if is_prime(value_for_primality_check):
|
170
|
+
if is_prime(value_for_primality_check): # is_prime checks the relevant part (e.g., real part)
|
164
171
|
modified_value = None
|
165
172
|
if ask_counter == 0:
|
166
173
|
modified_value = added_value + ask_unit
|
@@ -169,15 +176,21 @@ def unified_generator(kececi_type, start_input_raw, add_input_base_scalar, itera
|
|
169
176
|
modified_value = added_value - ask_unit
|
170
177
|
ask_counter = 0
|
171
178
|
sequence.append(modified_value)
|
172
|
-
|
179
|
+
actual_iterations_done += 1
|
180
|
+
if actual_iterations_done >= iterations:
|
181
|
+
result_value = modified_value # End with modified value if it's the last step
|
182
|
+
break
|
183
|
+
|
184
|
+
|
173
185
|
current_target_for_division_mod = modified_value
|
174
186
|
divided_after_modification = False
|
175
|
-
for divisor_candidate_mod in [primary_divisor, alternative_divisor]:
|
187
|
+
for divisor_candidate_mod in [primary_divisor, alternative_divisor]: # Re-use primary/alternative logic
|
176
188
|
can_divide_mod = False
|
177
189
|
if kececi_type in [1, 2]:
|
178
190
|
can_divide_mod = (current_target_for_division_mod % divisor_candidate_mod == 0)
|
179
191
|
elif kececi_type == 3:
|
180
|
-
can_divide_mod = math.isclose(current_target_for_division_mod.real % divisor_candidate_mod, 0)
|
192
|
+
can_divide_mod = math.isclose(current_target_for_division_mod.real % divisor_candidate_mod, 0) and \
|
193
|
+
math.isclose(current_target_for_division_mod.imag % divisor_candidate_mod, 0)
|
181
194
|
elif kececi_type == 4:
|
182
195
|
can_divide_mod = math.isclose(current_target_for_division_mod % divisor_candidate_mod, 0) or \
|
183
196
|
math.isclose(current_target_for_division_mod % divisor_candidate_mod, divisor_candidate_mod)
|
@@ -186,25 +199,32 @@ def unified_generator(kececi_type, start_input_raw, add_input_base_scalar, itera
|
|
186
199
|
quotient_rational_mod = current_target_for_division_mod / divisor_candidate_mod
|
187
200
|
can_divide_mod = (quotient_rational_mod.denominator == 1)
|
188
201
|
elif kececi_type == 6:
|
189
|
-
can_divide_mod = math.isclose(current_target_for_division_mod.w % divisor_candidate_mod, 0)
|
202
|
+
can_divide_mod = math.isclose(current_target_for_division_mod.w % divisor_candidate_mod, 0) and \
|
203
|
+
math.isclose(current_target_for_division_mod.x % divisor_candidate_mod, 0) and \
|
204
|
+
math.isclose(current_target_for_division_mod.y % divisor_candidate_mod, 0) and \
|
205
|
+
math.isclose(current_target_for_division_mod.z % divisor_candidate_mod, 0)
|
206
|
+
|
190
207
|
|
191
208
|
if can_divide_mod:
|
192
209
|
if use_integer_division:
|
193
210
|
result_value = current_target_for_division_mod // divisor_candidate_mod
|
194
211
|
else:
|
195
212
|
result_value = current_target_for_division_mod / divisor_candidate_mod
|
196
|
-
last_divisor_used = divisor_candidate_mod
|
213
|
+
last_divisor_used = divisor_candidate_mod # Update last_divisor_used
|
197
214
|
divided_after_modification = True
|
198
215
|
break
|
199
216
|
if not divided_after_modification:
|
200
217
|
result_value = modified_value
|
201
|
-
else:
|
218
|
+
else: # Not prime and not divisible
|
202
219
|
result_value = added_value
|
203
220
|
|
204
221
|
sequence.append(result_value)
|
222
|
+
actual_iterations_done += 1
|
223
|
+
if actual_iterations_done >= iterations: break
|
205
224
|
current_value = result_value
|
206
225
|
|
207
|
-
return sequence
|
226
|
+
return sequence[:iterations+1] # Ensure correct length, as we add start + iterations*2 steps
|
227
|
+
|
208
228
|
|
209
229
|
# --- Control Mechanisms (Exportable Functions) ---
|
210
230
|
def get_interactive():
|
@@ -227,8 +247,8 @@ def get_interactive():
|
|
227
247
|
except ValueError: print("Please enter a numeric value.")
|
228
248
|
|
229
249
|
start_prompt = "Enter the starting number (e.g., 0 or 2.5, complex:3+4j, rational: 3/4, quaternions: 1) : "
|
230
|
-
if type_choice == 3: start_prompt
|
231
|
-
elif type_choice == 5: start_prompt
|
250
|
+
if type_choice == 3: start_prompt = "Enter starting complex number (e.g., 3+4j or just 3 for 3+3j): "
|
251
|
+
elif type_choice == 5: start_prompt = "Enter starting rational (e.g., 7/2 or 5 for 5/1): "
|
232
252
|
|
233
253
|
start_input_val_raw = input(start_prompt)
|
234
254
|
|
@@ -240,12 +260,27 @@ def get_interactive():
|
|
240
260
|
|
241
261
|
while True:
|
242
262
|
try:
|
243
|
-
|
244
|
-
|
245
|
-
|
263
|
+
# Iterations'ı Keçeci adımları olarak düşünelim (her adımda 2 sayı eklenir: added_value, result_value)
|
264
|
+
num_kececi_steps = int(input("Enter the number of Keçeci steps (positive integer: e.g., 15, generates ~30 numbers): "))
|
265
|
+
if num_kececi_steps > 0: break
|
266
|
+
else: print("Number of Keçeci steps must be positive.")
|
246
267
|
except ValueError: print("Please enter an integer value.")
|
247
268
|
|
248
|
-
|
269
|
+
generated_sequence = unified_generator(type_choice, start_input_val_raw, add_base_scalar_val, num_kececi_steps)
|
270
|
+
|
271
|
+
# *** YENİ EKLENEN KISIM BAŞLANGICI ***
|
272
|
+
if generated_sequence:
|
273
|
+
print(f"\nGenerated Keçeci Sequence (first 20 of {len(generated_sequence)}): {generated_sequence[:20]}...")
|
274
|
+
kpn = find_kececi_prime_number(generated_sequence)
|
275
|
+
if kpn is not None:
|
276
|
+
print(f"Keçeci Prime Number for this sequence: {kpn}")
|
277
|
+
else:
|
278
|
+
print("No Keçeci Prime Number found for this sequence.")
|
279
|
+
else:
|
280
|
+
print("No sequence generated.")
|
281
|
+
# *** YENİ EKLENEN KISIM SONU ***
|
282
|
+
|
283
|
+
return generated_sequence # Fonksiyon yine de diziyi döndürmeli
|
249
284
|
|
250
285
|
def get_with_params(kececi_type_choice, iterations, start_value_raw="0", add_value_base_scalar=9.0, fixed_params=True, random_range_factor=10):
|
251
286
|
"""
|
@@ -257,33 +292,49 @@ def get_with_params(kececi_type_choice, iterations, start_value_raw="0", add_val
|
|
257
292
|
actual_add_base = add_value_base_scalar
|
258
293
|
|
259
294
|
if not fixed_params:
|
260
|
-
|
261
|
-
if kececi_type_choice == 1: # Positive
|
295
|
+
if kececi_type_choice == 1:
|
262
296
|
actual_start_raw = str(random.randint(0, int(random_range_factor)))
|
263
297
|
actual_add_base = float(random.randint(1, int(random_range_factor*1.5)))
|
264
|
-
elif kececi_type_choice == 2:
|
298
|
+
elif kececi_type_choice == 2:
|
265
299
|
actual_start_raw = str(random.randint(-int(random_range_factor), 0))
|
266
300
|
actual_add_base = float(random.randint(-int(random_range_factor*1.5), -1))
|
267
|
-
elif kececi_type_choice == 3:
|
268
|
-
|
301
|
+
elif kececi_type_choice == 3:
|
302
|
+
re_start = random.uniform(-random_range_factor/2, random_range_factor/2)
|
303
|
+
im_start = random.uniform(-random_range_factor/2, random_range_factor/2)
|
304
|
+
actual_start_raw = f"{re_start}{im_start:+}j" # String formatında complex
|
269
305
|
actual_add_base = random.uniform(1, random_range_factor/2)
|
270
|
-
elif kececi_type_choice == 4:
|
306
|
+
elif kececi_type_choice == 4:
|
271
307
|
actual_start_raw = str(random.uniform(-random_range_factor, random_range_factor))
|
272
308
|
actual_add_base = random.uniform(0.1, random_range_factor/2)
|
273
|
-
elif kececi_type_choice == 5:
|
309
|
+
elif kececi_type_choice == 5:
|
274
310
|
num = random.randint(-random_range_factor, random_range_factor)
|
275
311
|
den = random.randint(1, int(random_range_factor/2) if random_range_factor/2 >=1 else 1)
|
276
312
|
actual_start_raw = f"{num}/{den}"
|
277
313
|
actual_add_base = float(random.randint(1,random_range_factor))
|
278
|
-
elif kececi_type_choice == 6:
|
314
|
+
elif kececi_type_choice == 6:
|
315
|
+
# Quaternion için başlangıç ve ekleme skaler olsun, unified_generator q(s,s,s,s) yapsın
|
279
316
|
actual_start_raw = str(random.uniform(-random_range_factor/2, random_range_factor/2))
|
280
317
|
actual_add_base = random.uniform(1, random_range_factor/2)
|
281
|
-
else:
|
282
|
-
if kececi_type_choice == 2 and actual_add_base > 0:
|
283
|
-
actual_add_base = -actual_add_base
|
318
|
+
else:
|
319
|
+
if kececi_type_choice == 2 and float(actual_add_base) > 0: # add_value_base_scalar float olabilir
|
320
|
+
actual_add_base = -abs(float(actual_add_base))
|
284
321
|
|
285
322
|
|
286
|
-
|
323
|
+
generated_sequence = unified_generator(kececi_type_choice, actual_start_raw, actual_add_base, iterations)
|
324
|
+
|
325
|
+
# *** YENİ EKLENEN KISIM BAŞLANGICI ***
|
326
|
+
if generated_sequence:
|
327
|
+
print(f"\nGenerated Keçeci Sequence (using get_with_params, first 20 of {len(generated_sequence)}): {generated_sequence[:20]}...")
|
328
|
+
kpn = find_kececi_prime_number(generated_sequence)
|
329
|
+
if kpn is not None:
|
330
|
+
print(f"Keçeci Prime Number for this sequence: {kpn}")
|
331
|
+
else:
|
332
|
+
print("No Keçeci Prime Number found for this sequence.")
|
333
|
+
else:
|
334
|
+
print("No sequence generated by get_with_params.")
|
335
|
+
# *** YENİ EKLENEN KISIM SONU ***
|
336
|
+
|
337
|
+
return generated_sequence
|
287
338
|
|
288
339
|
|
289
340
|
def get_random_type(num_iterations, use_fixed_params_for_selected_type=True,
|
@@ -293,13 +344,16 @@ def get_random_type(num_iterations, use_fixed_params_for_selected_type=True,
|
|
293
344
|
"""
|
294
345
|
random_type_choice = random.randint(1, 6)
|
295
346
|
type_names_list = ["Positive Integer", "Negative Integer", "Complex", "Float", "Rational", "Quaternion"]
|
296
|
-
print(f"
|
347
|
+
print(f"\nRandomly selected Keçeci Number Type: {random_type_choice} ({type_names_list[random_type_choice-1]})")
|
297
348
|
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
349
|
+
# get_with_params fonksiyonu zaten KPN'yi yazdıracak, bu yüzden burada tekrar yazdırmaya gerek yok.
|
350
|
+
# Sadece get_with_params'ı çağırıyoruz.
|
351
|
+
generated_sequence = get_with_params(random_type_choice, num_iterations,
|
352
|
+
start_value_raw=fixed_start_raw,
|
353
|
+
add_value_base_scalar=fixed_add_base_scalar,
|
354
|
+
fixed_params=use_fixed_params_for_selected_type,
|
355
|
+
random_range_factor=random_factor)
|
356
|
+
return generated_sequence # get_with_params zaten KPN yazdırıyor.
|
303
357
|
|
304
358
|
# --- Plotting Function (can be called from the notebook) ---
|
305
359
|
def plot_numbers(sequence, title="Keçeci Numbers"):
|
@@ -310,16 +364,25 @@ def plot_numbers(sequence, title="Keçeci Numbers"):
|
|
310
364
|
|
311
365
|
if not sequence:
|
312
366
|
print("Sequence is empty, nothing to plot.")
|
367
|
+
plt.title(title + " (Empty Sequence)")
|
368
|
+
plt.text(0.5, 0.5, "Empty Sequence", ha='center', va='center', fontsize=16)
|
369
|
+
plt.show()
|
313
370
|
return
|
314
371
|
|
315
372
|
first_elem = sequence[0]
|
316
373
|
|
317
374
|
if isinstance(first_elem, np.quaternion):
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
375
|
+
# Filter out non-quaternion if any mixed types (should not happen with unified_generator)
|
376
|
+
q_sequence = [q for q in sequence if isinstance(q, np.quaternion)]
|
377
|
+
if not q_sequence:
|
378
|
+
print("No quaternion data to plot.")
|
379
|
+
plt.title(title + " (No Quaternion Data)")
|
380
|
+
plt.text(0.5, 0.5, "No Quaternion Data", ha='center', va='center', fontsize=16)
|
381
|
+
plt.show()
|
382
|
+
return
|
383
|
+
|
384
|
+
w_parts = [q.w for q in q_sequence]
|
385
|
+
vector_norms = [np.sqrt(q.x**2 + q.y**2 + q.z**2) for q in q_sequence]
|
323
386
|
|
324
387
|
plt.subplot(2, 1, 1)
|
325
388
|
plt.plot(w_parts, marker='o', linestyle='-', label='w (Scalar Part)')
|
@@ -332,8 +395,16 @@ def plot_numbers(sequence, title="Keçeci Numbers"):
|
|
332
395
|
plt.xlabel("Index"); plt.ylabel("Value"); plt.grid(True); plt.legend()
|
333
396
|
|
334
397
|
elif isinstance(first_elem, complex):
|
335
|
-
|
336
|
-
|
398
|
+
c_sequence = [c for c in sequence if isinstance(c, complex)]
|
399
|
+
if not c_sequence:
|
400
|
+
print("No complex data to plot.")
|
401
|
+
plt.title(title + " (No Complex Data)")
|
402
|
+
plt.text(0.5, 0.5, "No Complex Data", ha='center', va='center', fontsize=16)
|
403
|
+
plt.show()
|
404
|
+
return
|
405
|
+
|
406
|
+
real_parts = [n.real for n in c_sequence]
|
407
|
+
imag_parts = [n.imag for n in c_sequence]
|
337
408
|
|
338
409
|
plt.subplot(2, 1, 1)
|
339
410
|
plt.plot(real_parts, marker='o', linestyle='-', label='Real Part')
|
@@ -347,31 +418,113 @@ def plot_numbers(sequence, title="Keçeci Numbers"):
|
|
347
418
|
|
348
419
|
plt.figure(figsize=(8,8))
|
349
420
|
plt.plot(real_parts, imag_parts, marker='.', linestyle='-')
|
350
|
-
if real_parts:
|
351
|
-
plt.plot(real_parts[0], imag_parts[0], 'go', markersize=
|
352
|
-
plt.plot(real_parts[-1], imag_parts[-1], 'ro', markersize=
|
421
|
+
if real_parts: # Check if list is not empty
|
422
|
+
plt.plot(real_parts[0], imag_parts[0], 'go', markersize=10, label='Start')
|
423
|
+
plt.plot(real_parts[-1], imag_parts[-1], 'ro', markersize=10, label='End')
|
353
424
|
plt.title(title + " - Trajectory in Complex Plane"); plt.xlabel("Real Axis")
|
354
425
|
plt.ylabel("Imaginary Axis"); plt.axhline(0, color='black', lw=0.5)
|
355
426
|
plt.axvline(0, color='black', lw=0.5); plt.grid(True); plt.legend(); plt.axis('equal')
|
356
427
|
|
357
428
|
elif isinstance(first_elem, Fraction):
|
358
|
-
|
429
|
+
f_sequence = [f for f in sequence if isinstance(f, Fraction)]
|
430
|
+
if not f_sequence:
|
431
|
+
print("No rational data to plot.")
|
432
|
+
plt.title(title + " (No Rational Data)")
|
433
|
+
plt.text(0.5, 0.5, "No Rational Data", ha='center', va='center', fontsize=16)
|
434
|
+
plt.show()
|
435
|
+
return
|
436
|
+
float_sequence = [float(f) for f in f_sequence]
|
359
437
|
plt.plot(float_sequence, marker='o', linestyle='-')
|
360
438
|
plt.title(title + " (Rational Numbers - plotted as float)")
|
361
439
|
plt.xlabel("Index"); plt.ylabel("Value (float)"); plt.grid(True)
|
362
440
|
|
363
|
-
else:
|
441
|
+
else: # Integers, Floats, or mixed (if any error in generation)
|
364
442
|
try:
|
365
|
-
|
443
|
+
# Attempt to convert all to float for plotting
|
444
|
+
numeric_sequence = [float(x) for x in sequence if isinstance(x, (int, float, np.number))]
|
445
|
+
if not numeric_sequence: # If all were non-numeric after filtering
|
446
|
+
raise ValueError("No numeric data to plot after filtering.")
|
366
447
|
plt.plot(numeric_sequence, marker='o', linestyle='-')
|
367
|
-
except ValueError:
|
368
|
-
print("Sequence contains non-
|
369
|
-
|
448
|
+
except (ValueError, TypeError):
|
449
|
+
print(f"Warning: Sequence for '{title}' contains non-standard numeric or mixed types. Attempting basic plot.")
|
450
|
+
# Fallback for truly mixed or unplottable types: plot what you can as numbers
|
451
|
+
plottable_part = []
|
452
|
+
for x in sequence:
|
453
|
+
try: plottable_part.append(float(x))
|
454
|
+
except: pass # Ignore non-convertible
|
455
|
+
if plottable_part:
|
456
|
+
plt.plot(plottable_part, marker='o', linestyle='-')
|
457
|
+
else:
|
458
|
+
print("Could not plot any part of the sequence.")
|
459
|
+
plt.title(title + " (Non-Numeric or Unplottable Data)")
|
460
|
+
plt.text(0.5, 0.5, "Non-Numeric or Unplottable Data", ha='center', va='center', fontsize=16)
|
461
|
+
|
370
462
|
plt.title(title); plt.xlabel("Index")
|
371
463
|
plt.ylabel("Value"); plt.grid(True)
|
372
464
|
|
373
465
|
plt.tight_layout()
|
374
|
-
plt.show()
|
466
|
+
# plt.show() # Genellikle notebook'ta %matplotlib inline ile otomatik gösterilir.
|
467
|
+
# .py script'te bu satırın yorumunu kaldırmak gerekebilir.
|
468
|
+
|
469
|
+
def find_kececi_prime_number(kececi_numbers_list):
|
470
|
+
"""
|
471
|
+
Verilen Keçeci sayıları listesinden Keçeci Asal Sayısını bulur.
|
472
|
+
Keçeci Asal Sayısı, listede en sık tekrarlayan (veya reel/skaler kısmı asal olan) sayının
|
473
|
+
asal tamsayı temsilcisinin en sık tekrarlayanıdır.
|
474
|
+
Eğer frekanslar eşitse, daha büyük olan asal tamsayı temsilcisi tercih edilir.
|
475
|
+
"""
|
476
|
+
if not kececi_numbers_list:
|
477
|
+
# Modül içinde çağrıldığı için print yerine None dönmesi daha sessiz olur.
|
478
|
+
return None
|
479
|
+
|
480
|
+
integer_prime_representations = []
|
481
|
+
for num_original in kececi_numbers_list:
|
482
|
+
if is_prime(num_original):
|
483
|
+
value_checked = 0
|
484
|
+
if isinstance(num_original, (int, float)):
|
485
|
+
value_checked = abs(int(num_original))
|
486
|
+
elif isinstance(num_original, Fraction):
|
487
|
+
value_checked = abs(int(num_original))
|
488
|
+
elif isinstance(num_original, complex):
|
489
|
+
value_checked = abs(int(num_original.real))
|
490
|
+
elif isinstance(num_original, np.quaternion):
|
491
|
+
value_checked = abs(int(num_original.w))
|
492
|
+
else:
|
493
|
+
try:
|
494
|
+
value_checked = abs(int(num_original))
|
495
|
+
except (ValueError, TypeError):
|
496
|
+
continue
|
497
|
+
integer_prime_representations.append(value_checked)
|
498
|
+
|
499
|
+
if not integer_prime_representations:
|
500
|
+
return None
|
501
|
+
|
502
|
+
counts = collections.Counter(integer_prime_representations)
|
503
|
+
repeating_primes_info = []
|
504
|
+
for prime_int_val, freq in counts.items():
|
505
|
+
if freq > 1: # Sadece tekrarlayan asallar
|
506
|
+
repeating_primes_info.append((freq, prime_int_val))
|
507
|
+
|
508
|
+
if not repeating_primes_info:
|
509
|
+
return None
|
510
|
+
|
511
|
+
# En yüksek frekansa sahip olanı bul. Frekanslar eşitse,
|
512
|
+
# max() ikinci elemanı (prime_int_val) kullanarak büyük olanı seçer.
|
513
|
+
# (frekans, sayı) tuple'ları karşılaştırılır.
|
514
|
+
try:
|
515
|
+
best_freq, kececi_prime_integer = max(repeating_primes_info)
|
516
|
+
except ValueError: # repeating_primes_info boşsa (yukarıdaki if ile yakalanmalı ama ekstra güvence)
|
517
|
+
return None
|
518
|
+
|
519
|
+
return kececi_prime_integer
|
520
|
+
|
521
|
+
# Constants for Keçeci Types (makes it easier to use from outside)
|
522
|
+
TYPE_POSITIVE_REAL = 1
|
523
|
+
TYPE_NEGATIVE_REAL = 2
|
524
|
+
TYPE_COMPLEX = 3
|
525
|
+
TYPE_FLOAT = 4
|
526
|
+
TYPE_RATIONAL = 5
|
527
|
+
TYPE_QUATERNION = 6
|
375
528
|
|
376
529
|
# --- DEFINITIONS (as a multiline string, can be accessed as kececinumbers.DEFINITIONS) ---
|
377
530
|
DEFINITIONS = """
|
@@ -380,13 +533,13 @@ Keçeci NumberS UNIFIED DEFINITION
|
|
380
533
|
A Keçeci Number sequence is derived from a `start_input_raw` and an `add_input_base_scalar`.
|
381
534
|
These inputs are interpreted according to the selected Keçeci Number Type to become the `current_value` and a type-specific `_add_value_typed`.
|
382
535
|
|
383
|
-
In each step:
|
536
|
+
In each "Keçeci step" (which typically adds 2 or 3 numbers to the sequence):
|
384
537
|
1. `added_value = current_value + _add_value_typed`.
|
385
538
|
2. `added_value` is recorded in the sequence.
|
386
539
|
3. A `result_value` is obtained by applying the Division Rule and, if necessary, the ASK Rule to `added_value`.
|
387
540
|
4. `result_value` is recorded in the sequence.
|
388
541
|
5. `current_value = result_value`.
|
389
|
-
This process is repeated for the specified `number_of_iterations
|
542
|
+
This process is repeated for the specified `number_of_iterations` (Keçeci steps).
|
390
543
|
|
391
544
|
Division Rule:
|
392
545
|
* A `last_divisor_used` (2 or 3) is tracked.
|
@@ -394,6 +547,7 @@ Division Rule:
|
|
394
547
|
* `alternative_divisor`: The other of `primary_divisor` (2 or 3).
|
395
548
|
* `value_to_check_division`: This is `added_value` (or `modified_value` after ASK).
|
396
549
|
* The part of this value used for divisibility depends on the number type (e.g., real/scalar part for complex/quaternion, the fraction itself for rational).
|
550
|
+
* For Complex/Quaternion, all components should be divisible by the integer divisor for perfect division.
|
397
551
|
* First, division by `primary_divisor` is attempted:
|
398
552
|
* If `value_to_check_division` (or its relevant part) is "perfectly divisible" by `primary_divisor` (in a type-specific sense, e.g., for rationals, the result is an integer),
|
399
553
|
then `result_value = value_to_check_division / primary_divisor`. `last_divisor_used = primary_divisor`.
|
@@ -402,7 +556,7 @@ Division Rule:
|
|
402
556
|
then `result_value = value_to_check_division / alternative_divisor`. `last_divisor_used = alternative_divisor`.
|
403
557
|
|
404
558
|
Primality and ASK (Augment/Shrink then Check) Rule (if Division Fails):
|
405
|
-
* `value_for_primality_check`: The part/representation of `added_value` used for primality testing (e.g., integer part, real part).
|
559
|
+
* `value_for_primality_check`: The part/representation of `added_value` used for primality testing (e.g., integer part of real, real part of complex).
|
406
560
|
* If `is_prime(value_for_primality_check)` is true:
|
407
561
|
* An `ask_counter` (0 or 1) is used.
|
408
562
|
* `ask_unit`: A type-specific unit value (e.g., 1 for real, 1+1j for complex, Fraction(1,1) for rational, quaternion(1,1,1,1) for quaternion).
|
@@ -426,7 +580,7 @@ Number Types and Specifics:
|
|
426
580
|
* ASK unit: `1`. Primality: `abs(int(number))`.
|
427
581
|
3. Complex Numbers (`complex`):
|
428
582
|
* Start/Increment: Complex numbers. Scalar input `s` is interpreted as `s+sj` for start, and scalar `a` as `a+aj` for increment.
|
429
|
-
* Division: Complex division (`/`). Perfect divisibility:
|
583
|
+
* Division: Complex division (`/`). Perfect divisibility: Both real and imaginary parts are `math.isclose(part % integer_divisor, 0)`.
|
430
584
|
* ASK unit: `1+1j`. Primality: `abs(int(number.real))`.
|
431
585
|
4. Floating-Point Numbers (Treated as Float):
|
432
586
|
* Start/Increment: Decimal numbers.
|
@@ -438,20 +592,11 @@ Number Types and Specifics:
|
|
438
592
|
* ASK unit: `Fraction(1,1)`. Primality: `abs(int(fraction))`.
|
439
593
|
6. Quaternions (`numpy.quaternion`):
|
440
594
|
* Start/Increment: Quaternions. Scalar input `s` is interpreted as `q(s,s,s,s)` for start, and scalar `a` as `q(a,a,a,a)` for increment.
|
441
|
-
* Division: Quaternion division (`/`). Perfect divisibility:
|
595
|
+
* Division: Quaternion division (`/`). Perfect divisibility: All w,x,y,z parts are `math.isclose(part % integer_divisor, 0)`.
|
442
596
|
* ASK unit: `quaternion(1,1,1,1)`. Primality: `abs(int(number.w))`.
|
443
597
|
"""
|
444
598
|
|
445
|
-
# Constants for Kececi Types (makes it easier to use from outside)
|
446
|
-
TYPE_POSITIVE_REAL = 1
|
447
|
-
TYPE_NEGATIVE_REAL = 2
|
448
|
-
TYPE_COMPLEX = 3
|
449
|
-
TYPE_FLOAT = 4
|
450
|
-
TYPE_RATIONAL = 5
|
451
|
-
TYPE_QUATERNION = 6
|
452
599
|
|
453
|
-
# You can remove the __main__ block if this is purely a module
|
454
|
-
# or keep it for testing the module directly.
|
455
600
|
if __name__ == "__main__":
|
456
601
|
print("Keçeci Numbers Module Loaded.")
|
457
602
|
print("This module provides functions to generate and plot Keçeci Numbers.")
|
@@ -461,15 +606,23 @@ if __name__ == "__main__":
|
|
461
606
|
print("- kn.get_with_params(kececi_type, iterations, ...)")
|
462
607
|
print("- kn.get_random_type(iterations, ...)")
|
463
608
|
print("- kn.plot_numbers(sequence, title)")
|
609
|
+
print("- kn.find_kececi_prime_number(sequence)") # Explicitly list it
|
464
610
|
print("- kn.unified_generator(...) (low-level)")
|
465
|
-
print("\nAccess definitions
|
611
|
+
print("\nAccess definitions by printing kn.DEFINITIONS") # Changed to instruction
|
466
612
|
print("\nAccess type constants like: kn.TYPE_COMPLEX")
|
467
613
|
|
468
|
-
|
469
|
-
|
470
|
-
test_seq = get_with_params(TYPE_COMPLEX,
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
614
|
+
print("\nRunning a quick test for Complex numbers (fixed params, 5 Keçeci steps):")
|
615
|
+
# `iterations` in get_with_params is number of Keçeci steps
|
616
|
+
test_seq = get_with_params(TYPE_COMPLEX, 5, start_value_raw="1+1j", add_value_base_scalar=2.0, fixed_params=True)
|
617
|
+
# KPN will be printed by get_with_params
|
618
|
+
|
619
|
+
# Example of calling find_kececi_prime_number directly if needed
|
620
|
+
# if test_seq:
|
621
|
+
# kpn_direct = find_kececi_prime_number(test_seq)
|
622
|
+
# if kpn_direct is not None:
|
623
|
+
# print(f"Direct call to find_kececi_prime_number result: {kpn_direct}")
|
624
|
+
# else:
|
625
|
+
# print("Direct call: No Keçeci Prime Number found.")
|
626
|
+
|
627
|
+
# print("\nRunning a quick test for Negative Integers (10 Keçeci steps):")
|
628
|
+
# test_seq_neg = get_random_type(num_iterations=10) # KPN will be printed
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: kececinumbers
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.5
|
4
4
|
Summary: Keçeci Numbers An Exploration of a Dynamic Sequence Across Diverse Number Sets
|
5
5
|
Home-page: https://github.com/WhiteSymmetry/kececinumbers
|
6
6
|
Author: Mehmet Keçeci
|
@@ -149,6 +149,41 @@ Enter the number of iterations (positive integer: e.g., 30): 30
|
|
149
149
|
|
150
150
|

|
151
151
|
|
152
|
+
---
|
153
|
+
# Keçeci Prime Number
|
154
|
+
|
155
|
+
```python
|
156
|
+
import matplotlib.pyplot as plt
|
157
|
+
import kececinumbers as kn
|
158
|
+
|
159
|
+
|
160
|
+
print("--- Interactive Test ---")
|
161
|
+
seq_interactive = kn.get_interactive()
|
162
|
+
if seq_interactive:
|
163
|
+
kn.plot_numbers(seq_interactive, "Keçeci Numbers")
|
164
|
+
|
165
|
+
print("\n--- Random Type Test (60 Keçeci Steps) ---")
|
166
|
+
# num_iterations burada Keçeci adımı sayısıdır
|
167
|
+
seq_random = kn.get_random_type(num_iterations=60)
|
168
|
+
if seq_random:
|
169
|
+
kn.plot_numbers(seq_random, "Random Type Keçeci Numbers")
|
170
|
+
|
171
|
+
print("\n--- Fixed Params Test (Complex, 60 Keçeci Steps) ---")
|
172
|
+
seq_fixed = kn.get_with_params(
|
173
|
+
kececi_type_choice=kn.TYPE_COMPLEX,
|
174
|
+
iterations=60,
|
175
|
+
start_value_raw="1+2j",
|
176
|
+
add_value_base_scalar=3.0
|
177
|
+
)
|
178
|
+
if seq_fixed:
|
179
|
+
kn.plot_numbers(seq_fixed, "Fixed Params (Complex) Keçeci Numbers")
|
180
|
+
|
181
|
+
# İsterseniz find_kececi_prime_number'ı ayrıca da çağırabilirsiniz:
|
182
|
+
if seq_fixed:
|
183
|
+
kpn_direct = kn.find_kececi_prime_number(seq_fixed)
|
184
|
+
if kpn_direct is not None:
|
185
|
+
print(f"\nDirect call to find_kececi_prime_number for fixed numbers: {kpn_direct}")
|
186
|
+
```
|
152
187
|
---
|
153
188
|
|
154
189
|
## License / Lisans
|
@@ -3,7 +3,7 @@ from setuptools import setup, find_packages
|
|
3
3
|
|
4
4
|
setup(
|
5
5
|
name="kececinumbers",
|
6
|
-
version="0.1.
|
6
|
+
version="0.1.5",
|
7
7
|
description="Keçeci Numbers An Exploration of a Dynamic Sequence Across Diverse Number Sets",
|
8
8
|
long_description=open("README.md").read(),
|
9
9
|
long_description_content_type="text/markdown",
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|