kececinumbers 0.2.2__py3-none-any.whl → 0.3.0__py3-none-any.whl

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/__init__.py CHANGED
@@ -34,4 +34,4 @@ def eski_fonksiyon():
34
34
 
35
35
 
36
36
  # Paket sürüm numarası
37
- __version__ = "0.2.2"
37
+ __version__ = "0.3.0"
kececinumbers/_version.py CHANGED
@@ -1,6 +1,6 @@
1
1
  # _version.py
2
2
 
3
- __version__ = "0.2.2"
3
+ __version__ = "0.3.0"
4
4
  __license__ = "MIT"
5
5
  __description__ = "Keçeci Numbers: An Exploration of a Dynamic Sequence Across Diverse Number Sets."
6
6
  __author__ = "Mehmet Keçeci"
@@ -33,6 +33,7 @@ import matplotlib.pyplot as plt
33
33
  import numpy as np
34
34
  import quaternion # Requires: pip install numpy numpy-quaternion
35
35
  from matplotlib.gridspec import GridSpec
36
+ import re
36
37
 
37
38
  # ==============================================================================
38
39
  # --- MODULE CONSTANTS: KEÇECI NUMBER TYPES ---
@@ -53,24 +54,6 @@ TYPE_NEUTROSOPHIC_BICOMPLEX = 11
53
54
  # --- CUSTOM NUMBER CLASS DEFINITIONS ---
54
55
  # ==============================================================================
55
56
 
56
- def get_random_type(num_iterations, use_fixed_params_for_selected_type=True,
57
- fixed_start_raw="0", fixed_add_base_scalar=9.0, random_factor=10):
58
- """
59
- Generates Keçeci Numbers for a randomly selected type.
60
- """
61
- random_type_choice = random.randint(1, 6)
62
- type_names_list = ["Positive Integer", "Negative Integer", "Complex", "Float", "Rational", "Quaternion"]
63
- print(f"\nRandomly selected Keçeci Number Type: {random_type_choice} ({type_names_list[random_type_choice-1]})")
64
-
65
- # get_with_params fonksiyonu zaten KPN'yi yazdıracak, bu yüzden burada tekrar yazdırmaya gerek yok.
66
- # Sadece get_with_params'ı çağırıyoruz.
67
- generated_sequence = get_with_params(random_type_choice, num_iterations,
68
- start_value_raw=fixed_start_raw,
69
- add_value_base_scalar=fixed_add_base_scalar,
70
- fixed_params=use_fixed_params_for_selected_type,
71
- random_range_factor=random_factor)
72
- return generated_sequence # get_with_params zaten KPN yazdırıyor.
73
-
74
57
  @dataclass
75
58
  class NeutrosophicNumber:
76
59
  """
@@ -480,22 +463,19 @@ def _is_divisible(value, divisor, kececi_type):
480
463
 
481
464
  def unified_generator(kececi_type, start_input_raw, add_input_base_scalar, iterations):
482
465
  """
483
- The core engine for generating Keçeci Number sequences of any supported type.
484
- This version includes robust type conversion to prevent initialization errors.
466
+ Herhangi bir desteklenen türde Keçeci Sayı dizileri üreten çekirdek motor.
467
+ Bu sürüm, tüm tipler için sağlam tür dönüştürme ve özel format ayrıştırma içerir.
485
468
  """
486
- # --- Step 1: Initialization based on Keçeci Type ---
487
469
  current_value = None
488
470
  add_value_typed = None
489
471
  ask_unit = None
490
472
  use_integer_division = False
491
473
 
492
474
  try:
493
- # Convert the ADD value once, as it's always a scalar float.
475
+ # --- Adım 1: Keçeci Türüne Göre Başlatma ---
494
476
  a_float = float(add_input_base_scalar)
495
477
 
496
- # Handle START value conversion properly within each type-specific block.
497
478
  if kececi_type in [TYPE_POSITIVE_REAL, TYPE_NEGATIVE_REAL]:
498
- # Correctly handle float strings like "2.5" by converting to float first.
499
479
  s_int = int(float(start_input_raw))
500
480
  current_value = s_int
501
481
  add_value_typed = int(a_float)
@@ -508,82 +488,83 @@ def unified_generator(kececi_type, start_input_raw, add_input_base_scalar, itera
508
488
  ask_unit = 1.0
509
489
 
510
490
  elif kececi_type == TYPE_RATIONAL:
511
- # The Fraction constructor correctly handles strings like "2.5".
512
- current_value = Fraction(str(start_input_raw))
513
- add_value_typed = Fraction(str(add_input_base_scalar))
514
- ask_unit = Fraction(1, 1)
491
+ current_value = Fraction(start_input_raw)
492
+ add_value_typed = Fraction(add_input_base_scalar)
493
+ ask_unit = Fraction(1)
515
494
 
516
495
  elif kececi_type == TYPE_COMPLEX:
517
- s_complex = complex(start_input_raw)
518
- # If input was a plain number (e.g., "2.5"), interpret it as s+sj.
519
- if s_complex.imag == 0 and 'j' not in str(start_input_raw).lower():
520
- s_complex = complex(s_complex.real, s_complex.real)
521
- current_value = s_complex
496
+ current_value = _parse_complex(start_input_raw)
522
497
  add_value_typed = complex(a_float, a_float)
523
498
  ask_unit = 1 + 1j
524
499
 
525
- elif kececi_type == TYPE_QUATERNION:
526
- # Explicitly convert the input string to a float before use.
527
- s_float = float(start_input_raw)
528
- current_value = np.quaternion(s_float, s_float, s_float, s_float)
529
- add_value_typed = np.quaternion(a_float, a_float, a_float, a_float)
530
- ask_unit = np.quaternion(1, 1, 1, 1)
531
-
532
500
  elif kececi_type == TYPE_NEUTROSOPHIC:
533
- s_float = float(start_input_raw)
534
- current_value = NeutrosophicNumber(s_float, s_float / 2)
535
- add_value_typed = NeutrosophicNumber(a_float, a_float / 2)
501
+ a, b = _parse_neutrosophic(start_input_raw)
502
+ current_value = NeutrosophicNumber(a, b)
503
+ add_value_typed = NeutrosophicNumber(a_float, 0)
536
504
  ask_unit = NeutrosophicNumber(1, 1)
537
-
538
- elif kececi_type == TYPE_NEUTROSOPHIC_COMPLEX:
539
- s_float = float(start_input_raw)
540
- current_value = NeutrosophicComplexNumber(s_float, s_float / 2, s_float / 3)
541
- add_value_typed = NeutrosophicComplexNumber(a_float, a_float / 2, a_float / 3)
505
+
506
+ # --- YENİ EKLENEN/DÜZELTİLEN BLOKLAR ---
507
+
508
+ elif kececi_type == TYPE_NEUTROSOPHIC_COMPLEX: # HATA DÜZELTİLDİ
509
+ s_complex = _parse_complex(start_input_raw)
510
+ # Başlangıç indeterminacy değerini 0 olarak varsayalım
511
+ current_value = NeutrosophicComplexNumber(s_complex.real, s_complex.imag, 0.0)
512
+ # Artış, deterministik reel kısma etki eder
513
+ add_value_typed = NeutrosophicComplexNumber(a_float, 0.0, 0.0)
542
514
  ask_unit = NeutrosophicComplexNumber(1, 1, 1)
543
-
544
- elif kececi_type == TYPE_HYPERREAL:
545
- s_float = float(start_input_raw)
546
- current_value = HyperrealNumber([s_float / n for n in range(1, 11)])
547
- add_value_typed = HyperrealNumber([a_float / n for n in range(1, 11)])
515
+
516
+ elif kececi_type == TYPE_HYPERREAL: # HATA DÜZELTİLDİ
517
+ a, b = _parse_hyperreal(start_input_raw)
518
+ # 'a' reel kısmı, 'b' ise sonsuz küçükleri ölçekler
519
+ sequence_list = [a + b / n for n in range(1, 11)]
520
+ current_value = HyperrealNumber(sequence_list)
521
+ # Artış, sadece standart (ilk) reel kısma etki eder
522
+ add_sequence = [a_float] + [0.0] * 9
523
+ add_value_typed = HyperrealNumber(add_sequence)
548
524
  ask_unit = HyperrealNumber([1.0] * 10)
549
-
550
- elif kececi_type == TYPE_BICOMPLEX:
551
- s_complex = complex(start_input_raw)
525
+
526
+ elif kececi_type == TYPE_BICOMPLEX: # Mantık aynı, sadece ayrıştırıcıyı kullanıyor
527
+ s_complex = _parse_complex(start_input_raw)
552
528
  a_complex = complex(a_float)
553
529
  current_value = BicomplexNumber(s_complex, s_complex / 2)
554
530
  add_value_typed = BicomplexNumber(a_complex, a_complex / 2)
555
531
  ask_unit = BicomplexNumber(complex(1, 1), complex(0.5, 0.5))
556
532
 
557
- elif kececi_type == TYPE_NEUTROSOPHIC_BICOMPLEX:
533
+ elif kececi_type == TYPE_NEUTROSOPHIC_BICOMPLEX: # HATA DÜZELTİLDİ
534
+ s_complex = _parse_complex(start_input_raw)
535
+ # Başlangıç değeri olarak kompleks sayıyı kullanıp diğer 6 bileşeni 0 yapalım
536
+ current_value = NeutrosophicBicomplexNumber(s_complex.real, s_complex.imag, 0, 0, 0, 0, 0, 0)
537
+ # Artış, sadece ana reel kısma etki eder
538
+ add_value_typed = NeutrosophicBicomplexNumber(a_float, 0, 0, 0, 0, 0, 0, 0)
539
+ ask_unit = NeutrosophicBicomplexNumber(*([1.0] * 8))
540
+
541
+ # --- DİĞER TİPLER ---
542
+
543
+ elif kececi_type == TYPE_QUATERNION:
558
544
  s_float = float(start_input_raw)
559
- parts = [s_float / (n + 1) for n in range(8)]
560
- add_parts = [a_float / (n + 1) for n in range(8)]
561
- ask_parts = [1.0 / (n + 1) for n in range(8)]
562
- current_value = NeutrosophicBicomplexNumber(*parts)
563
- add_value_typed = NeutrosophicBicomplexNumber(*add_parts)
564
- ask_unit = NeutrosophicBicomplexNumber(*ask_parts)
565
-
545
+ current_value = np.quaternion(s_float, s_float, s_float, s_float)
546
+ add_value_typed = np.quaternion(a_float, a_float, a_float, a_float)
547
+ ask_unit = np.quaternion(1, 1, 1, 1)
548
+
566
549
  else:
567
- raise ValueError(f"Invalid Keçeci Number Type: {kececi_type}")
550
+ raise ValueError(f"Geçersiz veya desteklenmeyen Keçeci Sayı Tipi: {kececi_type}")
568
551
 
569
552
  except (ValueError, TypeError) as e:
570
- print(f"Error initializing generator for type {kececi_type} with input '{start_input_raw}': {e}")
553
+ print(f"HATA: Tip {kececi_type} için '{start_input_raw}' girdisiyle başlatma başarısız: {e}")
571
554
  return []
572
555
 
573
- # --- Step 2: Iteration Loop (This part remains unchanged) ---
556
+ # --- Adım 2: İterasyon Döngüsü ---
574
557
  sequence = [current_value]
575
558
  last_divisor_used = None
576
559
  ask_counter = 0
577
560
 
578
561
  for _ in range(iterations):
579
- # Rule 1: Add the increment value
580
562
  added_value = current_value + add_value_typed
581
563
  sequence.append(added_value)
582
564
 
583
565
  result_value = added_value
584
566
  divided_successfully = False
585
567
 
586
- # Rule 2: Attempt Division
587
568
  primary_divisor = 3 if last_divisor_used == 2 or last_divisor_used is None else 2
588
569
  alternative_divisor = 2 if primary_divisor == 3 else 3
589
570
 
@@ -594,16 +575,13 @@ def unified_generator(kececi_type, start_input_raw, add_input_base_scalar, itera
594
575
  divided_successfully = True
595
576
  break
596
577
 
597
- # Rule 3: Apply ASK Rule if division failed and the number is prime
598
578
  if not divided_successfully and is_prime(added_value):
599
- # Augment or Shrink the value
600
579
  modified_value = (added_value + ask_unit) if ask_counter == 0 else (added_value - ask_unit)
601
- ask_counter = 1 - ask_counter # Flip between 0 and 1
580
+ ask_counter = 1 - ask_counter
602
581
  sequence.append(modified_value)
603
582
 
604
- result_value = modified_value # Default to modified value if re-division fails
583
+ result_value = modified_value
605
584
 
606
- # Re-attempt division on the modified value
607
585
  for divisor in [primary_divisor, alternative_divisor]:
608
586
  if _is_divisible(modified_value, divisor, kececi_type):
609
587
  result_value = modified_value // divisor if use_integer_division else modified_value / divisor
@@ -615,6 +593,205 @@ def unified_generator(kececi_type, start_input_raw, add_input_base_scalar, itera
615
593
 
616
594
  return sequence
617
595
 
596
+ def _parse_complex(s: str) -> complex:
597
+ """
598
+ Bir string'i kompleks sayıya çevirir.
599
+ Eğer 'j' içermiyorsa, "3" girdisini 3+3j olarak yorumlar.
600
+ """
601
+ s_clean = s.strip().lower()
602
+ try:
603
+ # Doğrudan kompleks çevirmeyi dene (ör: "3+4j")
604
+ c = complex(s_clean)
605
+ # Eğer girdi "3" gibi sadece reel bir sayıysa ve 'j' içermiyorsa,
606
+ # onu s_complex.real + s_complex.real*j yap.
607
+ if c.imag == 0 and 'j' not in s_clean:
608
+ return complex(c.real, c.real)
609
+ return c
610
+ except ValueError as e:
611
+ raise ValueError(f"Geçersiz kompleks sayı formatı: '{s}'") from e
612
+
613
+ def _parse_neutrosophic(s: str) -> (float, float):
614
+ """
615
+ Parses a neutrosophic number string of the form 'a+bI' into a tuple (a, b).
616
+ Handles cases like '5+2I', '3-I', '7', '4I', '-I'.
617
+ """
618
+ s = s.strip().replace(" ", "").upper()
619
+ if not s:
620
+ return 0.0, 0.0
621
+
622
+ # Eğer 'I' yoksa, bu standart bir sayıdır (b=0)
623
+ if 'I' not in s:
624
+ try:
625
+ return float(s), 0.0
626
+ except ValueError:
627
+ raise ValueError(f"Invalid number format for non-neutrosophic part: {s}")
628
+
629
+ # 'I' varsa, a ve b kısımlarını ayır
630
+ # 'b' kısmını bul
631
+ i_pos = s.find('I')
632
+ a_part_str = s[:i_pos]
633
+
634
+ # Sadece 'I' veya '-I' gibi durumlar
635
+ if not a_part_str or a_part_str == '+':
636
+ b = 1.0
637
+ elif a_part_str == '-':
638
+ b = -1.0
639
+ else:
640
+ # 'a' ve 'b' kısımlarını ayırmak için sondaki işareti bul
641
+ last_plus = a_part_str.rfind('+')
642
+ last_minus = a_part_str.rfind('-')
643
+
644
+ # Eğer başta eksi işareti varsa onu ayraç olarak sayma
645
+ if last_minus == 0 and last_plus == -1:
646
+ split_pos = -1
647
+ else:
648
+ split_pos = max(last_plus, last_minus)
649
+
650
+ if split_pos == -1: # Örneğin '3I' durumu
651
+ a = 0.0
652
+ b = float(a_part_str)
653
+ else: # Örneğin '5+3I' veya '-2-4I' durumu
654
+ a = float(a_part_str[:split_pos])
655
+ b_str = a_part_str[split_pos:]
656
+ if b_str == '+':
657
+ b = 1.0
658
+ elif b_str == '-':
659
+ b = -1.0
660
+ else:
661
+ b = float(b_str)
662
+
663
+ return a, b
664
+
665
+ def _parse_hyperreal(s: str) -> (float, float):
666
+ """
667
+ 'a+be' formatındaki bir hiperreel string'i (a, b) demetine ayrıştırır.
668
+ '5+3e', '-2-e', '10', '4e', '-e' gibi formatları işler.
669
+ """
670
+ s = s.strip().replace(" ", "").lower()
671
+ if not s:
672
+ return 0.0, 0.0
673
+
674
+ # Eğer 'e' yoksa, bu standart bir sayıdır (b=0)
675
+ if 'e' not in s:
676
+ return float(s), 0.0
677
+
678
+ # 'a+be' formatını regex ile ayrıştır
679
+ # Örnekler: 5+3e, -3.1-4.5e, +2e, e, -e
680
+ match = re.match(r"^(?P<a>[+-]?\d+\.?\d*)?(?P<b>[+-]?\d*\.?\d*)e$", s)
681
+ if not match:
682
+ # Sadece +e veya -e durumları için
683
+ match = re.match(r"^(?P<a>[+-]?\d+\.?\d*)?(?P<b>[+-])e$", s)
684
+
685
+ if not match:
686
+ raise ValueError(f"Geçersiz hiperreel format: {s}")
687
+
688
+ parts = match.groupdict()
689
+ a_part = parts.get('a')
690
+ b_part = parts.get('b')
691
+
692
+ a = float(a_part) if a_part else 0.0
693
+
694
+ if b_part is None or b_part == '' or b_part == '+':
695
+ b = 1.0
696
+ elif b_part == '-':
697
+ b = -1.0
698
+ else:
699
+ b = float(b_part)
700
+
701
+ return a, b
702
+
703
+
704
+ def get_random_type(num_iterations, fixed_start_raw="0", fixed_add_base_scalar=9.0):
705
+ """
706
+ Generates Keçeci Numbers for a randomly selected type using fixed parameters.
707
+ (Updated with the full list of 11 types and compatible with the new get_with_params signature)
708
+ """
709
+ # Rastgele sayı üretme aralığı 11 tipe göre güncellendi.
710
+ random_type_choice = random.randint(1, 11)
711
+
712
+ # Kullanıcının sağladığı tam liste eklendi.
713
+ type_names_list = [
714
+ "Positive Real", "Negative Real", "Complex", "Float", "Rational",
715
+ "Quaternion", "Neutrosophic", "Neutro-Complex", "Hyperreal",
716
+ "Bicomplex", "Neutro-Bicomplex"
717
+ ]
718
+
719
+ # Listenin indeksi 0'dan başladığı için random_type_choice-1 kullanılır.
720
+ print(f"\nRandomly selected Keçeci Number Type: {random_type_choice} ({type_names_list[random_type_choice-1]})")
721
+
722
+ # get_with_params fonksiyonu sadeleştirilmiş haliyle çağrılıyor.
723
+ # Beklenmeyen 'random_range_factor' veya 'fixed_params' argümanları yok.
724
+ generated_sequence = get_with_params(
725
+ kececi_type_choice=random_type_choice,
726
+ iterations=num_iterations,
727
+ start_value_raw=fixed_start_raw,
728
+ add_value_base_scalar=fixed_add_base_scalar
729
+ )
730
+
731
+ return generated_sequence
732
+
733
+ def print_detailed_report(sequence, params):
734
+ """
735
+ Generates and prints a detailed report of the Keçeci sequence results.
736
+
737
+ Args:
738
+ sequence (list): The generated Keçeci sequence.
739
+ params (dict): A dictionary containing the generation parameters.
740
+ """
741
+ if not sequence:
742
+ print("\n--- REPORT ---")
743
+ print("Sequence could not be generated. No report to show.")
744
+ return
745
+
746
+ print("\n\n" + "="*50)
747
+ print("--- DETAILED SEQUENCE REPORT ---")
748
+ print("="*50)
749
+
750
+ # Parametreleri yazdır
751
+ print("\n[Parameters Used]")
752
+ print(f" - Keçeci Type: {params['type_name']} ({params['type_choice']})")
753
+ print(f" - Start Value: '{params['start_val']}'")
754
+ print(f" - Increment: {params['add_val']}")
755
+ print(f" - Keçeci Steps: {params['steps']}")
756
+
757
+ # Dizi Özeti
758
+ print("\n[Sequence Summary]")
759
+ print(f" - Total Numbers Generated: {len(sequence)}")
760
+
761
+ # Keçeci Asal Sayısı (KPN) sonucunu bul ve yazdır
762
+ kpn = find_kececi_prime_number(sequence)
763
+ if kpn is not None:
764
+ print(f" - Keçeci Prime Number (KPN): {kpn}")
765
+ else:
766
+ print(" - Keçeci Prime Number (KPN): Not found in this sequence.")
767
+
768
+ # Dizi Önizlemesi
769
+ print("\n[Sequence Preview]")
770
+ # Dizinin tamamını yazdırmadan önce bir önizleme sunalım
771
+ preview_count = min(len(sequence), 5)
772
+ print(f" --- First {preview_count} Numbers ---")
773
+ for i in range(preview_count):
774
+ print(f" {i}: {sequence[i]}")
775
+
776
+ if len(sequence) > preview_count:
777
+ print(f"\n --- Last {preview_count} Numbers ---")
778
+ for i in range(len(sequence) - preview_count, len(sequence)):
779
+ print(f" {i}: {sequence[i]}")
780
+
781
+ print("\n" + "="*50)
782
+
783
+ # Kullanıcıya tüm diziyi görmek isteyip istemediğini sor
784
+ while True:
785
+ show_all = input("Do you want to print the full sequence? (y/n): ").lower().strip()
786
+ if show_all in ['y', 'n']:
787
+ break
788
+
789
+ if show_all == 'y':
790
+ print("\n--- FULL SEQUENCE ---")
791
+ for i, num in enumerate(sequence):
792
+ print(f"{i}: {num}")
793
+ print("="*50)
794
+
618
795
  # ==============================================================================
619
796
  # --- HIGH-LEVEL CONTROL FUNCTIONS ---
620
797
  # ==============================================================================
@@ -648,6 +825,7 @@ def get_with_params(kececi_type_choice, iterations, start_value_raw="0", add_val
648
825
  def get_interactive():
649
826
  """
650
827
  Interactively gets parameters from the user and generates Keçeci Numbers.
828
+ This version only gets data and returns the sequence without plotting.
651
829
  """
652
830
  print("\n--- Keçeci Number Interactive Generator ---")
653
831
  print(" 1: Positive Real 2: Negative Real 3: Complex")
@@ -662,18 +840,38 @@ def get_interactive():
662
840
  else: print("Invalid type. Please enter a number between 1 and 11.")
663
841
  except ValueError: print("Invalid input. Please enter a number.")
664
842
 
665
- start_prompt = "Enter starting value: "
666
- if type_choice == TYPE_COMPLEX: start_prompt = "Enter complex start (e.g., '3+4j' or '3' for 3+3j): "
667
- elif type_choice == TYPE_RATIONAL: start_prompt = "Enter rational start (e.g., '7/2' or '5'): "
668
- elif type_choice == TYPE_BICOMPLEX: start_prompt = "Enter bicomplex start (complex, e.g., '2+1j'): "
843
+ # Her tip için özel başlangıç değeri istemleri (prompts)
844
+ prompts = {
845
+ 1: "Enter positive integer start (e.g., '10'): ",
846
+ 2: "Enter negative integer start (e.g., '-5'): ",
847
+ 3: "Enter complex start (e.g., '3+4j' or '3' for 3+3j): ",
848
+ 4: "Enter float start (e.g., '3.14' or '-0.5'): ",
849
+ 5: "Enter rational start (e.g., '7/2' or '5' for 5/1): ",
850
+ 6: "Enter scalar for quaternion base (e.g., '2.5' for 2.5+2.5i+2.5j+2.5k): ",
851
+ 7: "Enter neutrosophic start (e.g., '5+2I' or '7'): ",
852
+ 8: "Enter complex base for neutro-complex (e.g., '1-2j'): ",
853
+ 9: "Enter hyperreal start (e.g., '5+3e' or '10'): ",
854
+ 10: "Enter complex base for bicomplex (e.g., '2+1j'): ",
855
+ 11: "Enter complex base for neutro-bicomplex (e.g., '1+2j'): "
856
+ }
857
+
858
+ # Seçilen tipe göre doğru istemi al, yoksa genel bir istem kullan
859
+ start_prompt = prompts.get(type_choice, "Enter starting value: ")
669
860
 
670
861
  start_input_val_raw = input(start_prompt)
671
- add_base_scalar_val = float(input("Enter base scalar increment (e.g., 9.0): "))
862
+ add_base_scalar_val = float(input("Enter base scalar increment (e.g., 9.0 for positive, -3.0 for negative): "))
672
863
  num_kececi_steps = int(input("Enter number of Keçeci steps (e.g., 15): "))
673
864
 
865
+ # Diziyi oluştur ve çizdir
674
866
  sequence = get_with_params(type_choice, num_kececi_steps, start_input_val_raw, add_base_scalar_val)
675
- plot_numbers(sequence, f"Keçeci Type {type_choice} Sequence")
676
- plt.show()
867
+ if sequence:
868
+ # sequence adı altında bir isim çakışması olmaması için başlığı değiştiriyoruz.
869
+ plot_title = f"Keçeci Type {type_choice} Sequence"
870
+ #plot_numbers(sequence, plot_title)
871
+ #plt.show() # Grafiği göstermek için
872
+
873
+ # Fonksiyonun, ana kodun kullanabilmesi için tüm önemli bilgileri döndürmesini sağlıyoruz.
874
+ return sequence, type_choice, start_input_val_raw, add_base_scalar_val, num_kececi_steps
677
875
 
678
876
  # ==============================================================================
679
877
  # --- ANALYSIS AND PLOTTING ---
@@ -724,8 +922,8 @@ def find_kececi_prime_number(kececi_numbers_list):
724
922
 
725
923
  def plot_numbers(sequence, title="Keçeci Number Sequence Analysis"):
726
924
  """
727
- Plots the generated Keçeci Number sequence with appropriate visualizations
728
- for each number type.
925
+ Plots the generated Keçeci Number sequence with appropriate, detailed
926
+ visualizations for each number type.
729
927
  """
730
928
  plt.style.use('seaborn-v0_8-whitegrid')
731
929
 
@@ -733,25 +931,19 @@ def plot_numbers(sequence, title="Keçeci Number Sequence Analysis"):
733
931
  print("Sequence is empty, nothing to plot.")
734
932
  return
735
933
 
736
- fig = plt.figure(figsize=(15, 8))
934
+ fig = plt.figure(figsize=(16, 9)) # Daha geniş bir görünüm için boyut ayarlandı
737
935
  plt.suptitle(title, fontsize=16, y=0.98)
738
936
  first_elem = sequence[0]
739
937
 
740
- # --- Plotting logic per type ---
938
+ # --- Her Türe Özel Çizim Mantığı ---
741
939
 
742
- # CORRECTED: Check for the actual Python types.
743
- # This correctly handles types 1, 2, and 4 (Positive/Negative Real, Float).
744
- if isinstance(first_elem, (int, float)):
940
+ if isinstance(first_elem, (int, float, Fraction)):
745
941
  ax = fig.add_subplot(1, 1, 1)
746
- ax.plot([float(x) for x in sequence], 'o-')
942
+ ax.plot([float(x) for x in sequence], 'o-', label="Value")
747
943
  ax.set_title("Value over Iterations")
748
- ax.set_xlabel("Index"); ax.set_ylabel("Value")
749
-
750
- elif isinstance(first_elem, Fraction):
751
- ax = fig.add_subplot(1, 1, 1)
752
- ax.plot([float(x) for x in sequence], 'o-')
753
- ax.set_title("Value over Iterations (as float)")
754
- ax.set_xlabel("Index"); ax.set_ylabel("Value")
944
+ ax.set_xlabel("Index")
945
+ ax.set_ylabel("Value")
946
+ ax.legend()
755
947
 
756
948
  elif isinstance(first_elem, complex):
757
949
  gs = GridSpec(2, 2, figure=fig)
@@ -776,17 +968,18 @@ def plot_numbers(sequence, title="Keçeci Number Sequence Analysis"):
776
968
  elif isinstance(first_elem, np.quaternion):
777
969
  gs = GridSpec(2, 1, figure=fig)
778
970
  ax1 = fig.add_subplot(gs[0, 0])
779
- ax2 = fig.add_subplot(gs[1, 0])
971
+ ax2 = fig.add_subplot(gs[1, 0], sharex=ax1) # X eksenini paylaş
780
972
 
781
973
  ax1.plot([q.w for q in sequence], 'o-', label='w (scalar)')
782
974
  ax1.plot([q.x for q in sequence], 's--', label='x')
783
975
  ax1.plot([q.y for q in sequence], '^--', label='y')
784
976
  ax1.plot([q.z for q in sequence], 'd--', label='z')
785
- ax1.set_title("Quaternion Components"); ax1.legend()
977
+ ax1.set_title("Quaternion Components over Iterations"); ax1.legend()
786
978
 
787
979
  magnitudes = [np.sqrt(q.w**2 + q.x**2 + q.y**2 + q.z**2) for q in sequence]
788
980
  ax2.plot(magnitudes, 'o-', color='purple', label='Magnitude')
789
- ax2.set_title("Quaternion Magnitude"); ax2.legend()
981
+ ax2.set_title("Quaternion Magnitude over Iterations"); ax2.legend()
982
+ ax2.set_xlabel("Index")
790
983
 
791
984
  elif isinstance(first_elem, BicomplexNumber):
792
985
  gs = GridSpec(2, 2, figure=fig)
@@ -802,8 +995,8 @@ def plot_numbers(sequence, title="Keçeci Number Sequence Analysis"):
802
995
  ax2.plot(z2r, label='z2.real'); ax2.plot(z2i, label='z2.imag')
803
996
  ax2.set_title("Component z2"); ax2.legend()
804
997
 
805
- ax3.plot(z1r, z1i, '.-'); ax3.set_title("z1 in Complex Plane")
806
- ax4.plot(z2r, z2i, '.-'); ax4.set_title("z2 in Complex Plane")
998
+ ax3.plot(z1r, z1i, '.-'); ax3.set_title("z1 Trajectory"); ax3.set_xlabel("Real"); ax3.set_ylabel("Imaginary")
999
+ ax4.plot(z2r, z2i, '.-'); ax4.set_title("z2 Trajectory"); ax4.set_xlabel("Real"); ax4.set_ylabel("Imaginary")
807
1000
 
808
1001
  elif isinstance(first_elem, NeutrosophicNumber):
809
1002
  gs = GridSpec(1, 2, figure=fig)
@@ -811,25 +1004,72 @@ def plot_numbers(sequence, title="Keçeci Number Sequence Analysis"):
811
1004
 
812
1005
  a = [x.a for x in sequence]; b = [x.b for x in sequence]
813
1006
  ax1.plot(a, label='Determinate (a)'); ax1.plot(b, label='Indeterminate (b)')
814
- ax1.set_title("Components"); ax1.legend()
1007
+ ax1.set_title("Components over Iterations"); ax1.legend()
815
1008
 
816
1009
  sc = ax2.scatter(a, b, c=range(len(a)), cmap='viridis')
817
- ax2.set_title("Determinate vs. Indeterminate"); fig.colorbar(sc, ax=ax2)
1010
+ ax2.set_title("Trajectory (colored by time)"); ax2.set_xlabel("Determinate Part"); ax2.set_ylabel("Indeterminate Part"); fig.colorbar(sc, ax=ax2, label="Iteration")
818
1011
 
819
1012
  elif isinstance(first_elem, NeutrosophicComplexNumber):
820
- gs = GridSpec(1, 2, figure=fig)
821
- ax1 = fig.add_subplot(gs[0, 0]); ax2 = fig.add_subplot(gs[0, 1])
1013
+ gs = GridSpec(2, 1, figure=fig)
1014
+ ax1 = fig.add_subplot(gs[0, 0]); ax2 = fig.add_subplot(gs[1, 0])
822
1015
 
823
1016
  r = [x.real for x in sequence]; i = [x.imag for x in sequence]; ind = [x.indeterminacy for x in sequence]
824
1017
  ax1.plot(r, label='Real'); ax1.plot(i, label='Imag'); ax1.plot(ind, label='Indeterminacy', linestyle=':')
825
- ax1.set_title("Components"); ax1.legend()
1018
+ ax1.set_title("Components over Iterations"); ax1.legend()
826
1019
 
827
- sc = ax2.scatter(r, i, c=ind, cmap='magma')
828
- ax2.set_title("Complex Plane (colored by Indeterminacy)"); fig.colorbar(sc, ax=ax2, label='Indeterminacy')
1020
+ sc = ax2.scatter(r, i, c=ind, cmap='magma', s=20)
1021
+ ax2.set_title("Trajectory in Complex Plane (colored by Indeterminacy)");
1022
+ ax2.set_xlabel("Real Part"); ax2.set_ylabel("Imaginary Part");
1023
+ fig.colorbar(sc, ax=ax2, label='Indeterminacy')
1024
+ ax2.axis('equal')
1025
+
1026
+ # --- YENİ EKLENEN BLOKLAR ---
829
1027
 
830
- else: # Fallback for Hyperreal, Neutro-Bicomplex, and others
1028
+ elif isinstance(first_elem, HyperrealNumber):
1029
+ gs = GridSpec(2, 1, figure=fig)
1030
+ ax1 = fig.add_subplot(gs[0, 0])
1031
+ ax2 = fig.add_subplot(gs[1, 0])
1032
+
1033
+ # İlk birkaç bileşeni çiz
1034
+ num_components_to_plot = min(len(first_elem.sequence), 4)
1035
+ for i in range(num_components_to_plot):
1036
+ comp_data = [h.sequence[i] for h in sequence]
1037
+ ax1.plot(comp_data, label=f'Component {i}')
1038
+ ax1.set_title("Hyperreal Components over Iterations"); ax1.legend()
1039
+
1040
+ # En önemli iki bileşenin yörüngesini çiz
1041
+ comp0 = [h.sequence[0] for h in sequence]
1042
+ comp1 = [h.sequence[1] for h in sequence]
1043
+ sc = ax2.scatter(comp0, comp1, c=range(len(comp0)), cmap='plasma')
1044
+ ax2.set_title("Trajectory in Standard-Infinitesimal Plane (C0 vs C1)")
1045
+ ax2.set_xlabel("Standard Part (C0)"); ax2.set_ylabel("Primary Infinitesimal (C1)")
1046
+ fig.colorbar(sc, ax=ax2, label="Iteration")
1047
+
1048
+ elif isinstance(first_elem, NeutrosophicBicomplexNumber):
1049
+ gs = GridSpec(2, 2, figure=fig)
1050
+ ax1 = fig.add_subplot(gs[0, 0]); ax2 = fig.add_subplot(gs[0, 1])
1051
+ ax3 = fig.add_subplot(gs[1, 0]); ax4 = fig.add_subplot(gs[1, 1])
1052
+
1053
+ # Ana 4 yörüngeyi çizelim
1054
+ r = [n.real for n in sequence]; i = [n.imag for n in sequence]
1055
+ ax1.plot(r, i, '.-', label='(1, i1)')
1056
+ ax1.set_title("Primary Deterministic Plane"); ax1.legend()
1057
+
1058
+ nr = [n.neut_real for n in sequence]; ni = [n.neut_imag for n in sequence]
1059
+ ax2.plot(nr, ni, '.-', label='(I, I*i1)')
1060
+ ax2.set_title("Primary Neutrosophic Plane"); ax2.legend()
1061
+
1062
+ jr = [n.j_real for n in sequence]; ji = [n.j_imag for n in sequence]
1063
+ ax3.plot(jr, ji, '.-', label='(i2, i1*i2)')
1064
+ ax3.set_title("Secondary Deterministic Plane"); ax3.legend()
1065
+
1066
+ njr = [n.j_neut_real for n in sequence]; nji = [n.j_neut_imag for n in sequence]
1067
+ ax4.plot(njr, nji, '.-', label='(I*i2, I*i1*i2)')
1068
+ ax4.set_title("Secondary Neutrosophic Plane"); ax4.legend()
1069
+
1070
+ else: # Gelecekte eklenebilecek diğer tipler için yedek blok
831
1071
  ax = fig.add_subplot(1, 1, 1)
832
- ax.text(0.5, 0.5, f"Plotting for type '{type(first_elem).__name__}'\nis not specifically implemented.\nShowing string representation of first 3 elements:\n\n1. {sequence[0]}\n2. {sequence[1]}\n3. {sequence[2]}",
1072
+ ax.text(0.5, 0.5, f"Plotting for type '{type(first_elem).__name__}' is not specifically implemented.",
833
1073
  ha='center', va='center', fontsize=12, bbox=dict(facecolor='lightyellow'))
834
1074
 
835
1075
  plt.tight_layout(rect=[0, 0, 1, 0.96])
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kececinumbers
3
- Version: 0.2.2
3
+ Version: 0.3.0
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
7
- Author-email: bilginomi@yaani.com
7
+ Author-email: mkececi@yaani.com
8
8
  Maintainer: Mehmet Keçeci
9
- Maintainer-email: bilginomi@yaani.com
9
+ Maintainer-email: mkececi@yaani.com
10
10
  License: MIT
11
11
  Classifier: Programming Language :: Python :: 3
12
12
  Classifier: License :: OSI Approved :: MIT License
@@ -128,6 +128,49 @@ https://zenodo.org/records/
128
128
 
129
129
  ### Example
130
130
 
131
+ ```python
132
+ import matplotlib.pyplot as plt
133
+ import kececinumbers as kn
134
+
135
+ print("--- Interactive Test ---")
136
+
137
+ # Adım 1: get_interactive'ten tüm verileri al
138
+ # Not: Fonksiyon artık birden fazla değer döndürüyor.
139
+ interactive_results = kn.get_interactive()
140
+
141
+ # Fonksiyon bir dizi döndürdüyse (başarılıysa) devam et
142
+ if interactive_results and interactive_results[0]:
143
+ # Dönen değerleri değişkenlere ata
144
+ seq_interactive, type_choice, start_val, add_val, steps = interactive_results
145
+
146
+ # Tip numarasını isme çevirelim
147
+ type_names = [
148
+ "Positive Real", "Negative Real", "Complex", "Float", "Rational",
149
+ "Quaternion", "Neutrosophic", "Neutro-Complex", "Hyperreal",
150
+ "Bicomplex", "Neutro-Bicomplex"
151
+ ]
152
+ type_name = type_names[type_choice - 1]
153
+
154
+ # Adım 2: Ayrıntılı raporu yazdır
155
+ params = {
156
+ 'type_choice': type_choice,
157
+ 'type_name': type_name,
158
+ 'start_val': start_val,
159
+ 'add_val': add_val,
160
+ 'steps': steps
161
+ }
162
+ kn.print_detailed_report(seq_interactive, params)
163
+
164
+ # Adım 3: Grafiği SADECE BİR KERE çizdir
165
+ print("\nDisplaying plot...")
166
+ plot_title = f"Interactive Keçeci Sequence ({type_name})"
167
+ kn.plot_numbers(seq_interactive, plot_title)
168
+ plt.show()
169
+
170
+ else:
171
+ print("Sequence generation was cancelled or failed.")
172
+ ```
173
+
131
174
  ```python
132
175
  import matplotlib.pyplot as plt
133
176
  import random
@@ -135,9 +178,6 @@ import numpy as np
135
178
  import math
136
179
  from fractions import Fraction
137
180
  import quaternion # pip install numpy numpy-quaternion
138
- ```
139
- ```python
140
- import matplotlib.pyplot as plt
141
181
  import kececinumbers as kn
142
182
 
143
183
  # Matplotlib grafiklerinin notebook içinde gösterilmesini sağla
@@ -0,0 +1,8 @@
1
+ kececinumbers/__init__.py,sha256=PPcSRN9XDmCebyzqVkNUIv2lWsMGRc2F_C8QDv0DPL4,1427
2
+ kececinumbers/_version.py,sha256=4nBagc2NMpbf3Ot8Of1OyJ26DHuiiw3plqDzffzYx3Q,428
3
+ kececinumbers/kececinumbers.py,sha256=xQVXYKnhdm2-7ExXkTIPeIvV26Y4Z9flKXyCDdAG4qo,46489
4
+ kececinumbers-0.3.0.dist-info/licenses/LICENSE,sha256=NJZsJEbQuKzxn1mWPWCbRx8jRUqGS22thl8wwuRQJ9c,1071
5
+ kececinumbers-0.3.0.dist-info/METADATA,sha256=0T0kaFaiz7je-_aDd-USw6-QeTXmMftybMLcwVspLvQ,15394
6
+ kececinumbers-0.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
7
+ kececinumbers-0.3.0.dist-info/top_level.txt,sha256=VvlbQKmTjOlzBbvq54-AaXp_WPRZ5dOhw91lV-ytPRQ,14
8
+ kececinumbers-0.3.0.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- kececinumbers/__init__.py,sha256=JsyncFH_EvulqHonq8ZwQ0U320Pn6jQGnDQGZIZ9J2k,1427
2
- kececinumbers/_version.py,sha256=jUYrWHUGa7z5CqDjSpttj3lcGyBCIj6VN42MMCBWxL8,428
3
- kececinumbers/kececinumbers.py,sha256=HKzpmaTy59CGilyn5Y-fbgyjK4VftNPg_SbQi3EYW9s,37918
4
- kececinumbers-0.2.2.dist-info/licenses/LICENSE,sha256=NJZsJEbQuKzxn1mWPWCbRx8jRUqGS22thl8wwuRQJ9c,1071
5
- kececinumbers-0.2.2.dist-info/METADATA,sha256=euR0t75LxU49XvdiKOBoYWxQxYOCPHM2zByoQVMmlqg,14097
6
- kececinumbers-0.2.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
7
- kececinumbers-0.2.2.dist-info/top_level.txt,sha256=VvlbQKmTjOlzBbvq54-AaXp_WPRZ5dOhw91lV-ytPRQ,14
8
- kececinumbers-0.2.2.dist-info/RECORD,,