Ganzzahlenkette "umformen" bzw. komprimieren...

Anfängerfragen zum Programmieren mit PureBasic.
Ractur
Beiträge: 128
Registriert: 24.06.2008 11:51

Ganzzahlenkette "umformen" bzw. komprimieren...

Beitrag von Ractur »

Hallo,

ich suche einen Lösungsansatz wie man eine Ganzzahlenkette komprimieren kann diese aber noch "lesbar" bleibt und mit der Tastatur eingegeben werden kann.

Angenommen ich habe eine Ganzzahlenkette von 20 Ziffern (Immer die gleiche Länge) mit x-beliebiger Reihenfolge der Zahlen

unkomprimierte_kette = 12345678901234567890

und möchte diese nun komprimieren aber natürlich auch wieder dekomprimieren... Zum komprimieren können alle Zeichen der Tastatur verwendet werden, vorzüglich ABC und Zahlen oder nur Zahlen.

Könnte ich nun aus 12345678901234567890 z.B. komprimierte_kette = A2fs7d6213 machen
um nachher wieder aus komprimierte_kette = A2fs7d6213 die unkomprimierte_kette = 12345678901234567890 zu erzeugen?

Womöglich ist dies aber gar nicht möglich? :mrgreen:

Danke und Gruß Matthias
Ractur, der mit dem Programmierstil der 80er Jahre :D
Benutzeravatar
CodeCommander
Beiträge: 213
Registriert: 02.03.2014 16:06

Beitrag von CodeCommander »

~ DELETE ~
Zuletzt geändert von CodeCommander am 18.01.2015 14:38, insgesamt 1-mal geändert.
~ DELETE ~
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7028
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Ganzzahlenkette "umformen" bzw. komprimieren...

Beitrag von STARGÅTE »

Dafür kannst du Base64 nutzen.

Eine Zahl mit nur Zahlen kann nicht komprimiert werden, wenn weiterhin nur Zahlen erlaubt sind.

Was du nun machen kannst ist zB immer zwei Ziffern in ein Zeichen umzuwandeln, dann brauchst du jedoch 100 verschiedene Zeichen, und somit leider auch Sonderzeichen.

Was auch geht ist immer drei Ziffern in zwei Zeichen wanden, dann bachst du ~32 verschiedene Zeichen.

Oder du nimmst einfach Hex() und Val()

Code: Alles auswählen

Debug "12345678901234567890"
Debug Hex(Val("12345678901234567890"))
Debug StrU(Val("$"+Hex(Val("12345678901234567890"))))
geht allerdings nur bei 2^64-1
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8807
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: Ganzzahlenkette "umformen" bzw. komprimieren...

Beitrag von NicTheQuick »

Ich hatte da mal was gemacht, was Zahlen von einem Zahlensystem in ein anderes übersetzen kann. Wenn man eine Dezimalzahl übersetzt in das 36er-System, dann wird sie auch kürzer.

Code: Alles auswählen

 Procedure.s Base_Convert(Value.s, InBase.l = 10, OutBase.l = 2, nbDecimals.l = 100)
  Protected p.l, *c.Character, left.s, l.l, lout.s, Mod.l, out.s, rout.s, right.s, a.l
 
  *c = @Value
  While *c\c
    Select *c\c
      Case '0' To '9' : *c\c - '0' + 1
      Case 'a' To 'z' : *c\c - 'a' + 11
      Case 'A' To 'Z' : *c\c - 'A' + 11
      Case '.' ;do nothing
      Default : *c\c = 1
    EndSelect
    *c + SizeOf(Character)
  Wend
 
  p = FindString(Value, ".", 1)
  If p
    left = Left(Value, p - 1)
    right = Mid(Value, p + 1, Len(Value) - p)
  Else
    p = Len(Value)
    left = Value
    right = ""
  EndIf
 
  If left ;Vorkommateil
    While left <> ""
      Mod = 0 : *c = @left : out = ""
      While *c\c
        Mod = Mod * InBase + *c\c - 1
        l = Mod / OutBase
        If l Or out
          out + Chr(l + 1)
        EndIf
        Mod - (l * OutBase)
       
        *c + SizeOf(Character)
      Wend
     
      left = out
      lout = Chr(Mod + 1) + lout
    Wend
  Else
    lout = Chr(1)
  EndIf
 
  If right ;Nachkommateil
    a = 0
    p = Len(right)
    While right <> Chr(1) And a < nbDecimals
      *c = @right + (p - 1) * SizeOf(Character)
      p = 0 : Mod = 0 : out = ""
      While *c >= @right
        Mod + (*c\c - 1) * OutBase
        out = Chr((Mod % InBase) + 1) + out
        Mod / InBase
        *c - SizeOf(Character)
        p + 1
      Wend
     
      right = out
      rout + Chr(Mod + 1)
      a + 1
    Wend
  EndIf
 
  If rout : out = lout + "." + rout : Else : out = lout : EndIf
 
  *c = @out
  While *c\c
    Select *c\c
      Case 1 To 10 : *c\c + '0' - 1
      Case 11 To 36 : *c\c + 'A' - 11
      Case '.' ;do nothing
      Default : *c\c = '?'
    EndSelect
    *c + SizeOf(Character)
  Wend
 
  ProcedureReturn out
EndProcedure

Define unkomprimiert.s = "12345678901234567890"
Define komprimiert.s = Base_Convert(unkomprimiert, 10, 36, 100)
Define dekomprimiert.s = Base_Convert(komprimiert, 36, 10, 100)

Debug "Unkomprimiert: " + unkomprimiert
Debug "Komprimiert: " + komprimiert
Debug "Dekomprimiert: " + dekomprimiert
Jetzt könnte man den Code natürlich noch umbauen, sodass mehr als 36 verschiedene Zeichen gehen.

Übrigens kommt der Code auch mit beliebig langen Dezimalzahlen zurecht.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8807
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: Ganzzahlenkette "umformen" bzw. komprimieren...

Beitrag von NicTheQuick »

Noch schnell eine weitere Version. Diese geht bis zum 62er-System. Das heißt jede Ziffer kann 0-9, A-Z oder a-z sein.
Aus deiner 20-stelligen Zahl wird so eine 11-stellige.

Code: Alles auswählen

Procedure.s Base_Convert(Value.s, InBase.l = 10, OutBase.l = 2, nbDecimals.l = 100)
	Protected p.l, *c.Character, left.s, l.l, lout.s, Mod.l, out.s, rout.s, right.s, a.l
	
	*c = @Value
	While *c\c
		Select *c\c
			Case '0' To '9' : *c\c - '0' + 1
			Case 'A' To 'Z' : *c\c - 'A' + 11
			Case 'a' To 'z' : *c\c - 'a' + 11 + Bool(InBase > 36) * 26
			Case '.' ;do nothing
			Default : *c\c = 1
		EndSelect
		*c + SizeOf(Character)
	Wend
	
	p = FindString(Value, ".", 1)
	If p
		left = Left(Value, p - 1)
		right = Mid(Value, p + 1, Len(Value) - p)
	Else
		p = Len(Value)
		left = Value
		right = ""
	EndIf
	
	If left ;Vorkommateil
		While left <> ""
			Mod = 0 : *c = @left : out = ""
			While *c\c
				Mod = Mod * InBase + *c\c - 1
				l = Mod / OutBase
				If l Or out
					out + Chr(l + 1)
				EndIf
				Mod - (l * OutBase)
				
				*c + SizeOf(Character)
			Wend
			
			left = out
			lout = Chr(Mod + 1) + lout
		Wend
	Else
		lout = Chr(1)
	EndIf
	
	If right ;Nachkommateil
		a = 0
		p = Len(right)
		While right <> Chr(1) And a < nbDecimals
			*c = @right + (p - 1) * SizeOf(Character)
			p = 0 : Mod = 0 : out = ""
			While *c >= @right
				Mod + (*c\c - 1) * OutBase
				out = Chr((Mod % InBase) + 1) + out
				Mod / InBase
				*c - SizeOf(Character)
				p + 1
			Wend
			
			right = out
			rout + Chr(Mod + 1)
			a + 1
		Wend
	EndIf
	
	If rout : out = lout + "." + rout : Else : out = lout : EndIf
	
	*c = @out
	While *c\c
		Select *c\c
			Case 1 To 10 : *c\c + '0' - 1
			Case 11 To 36 : *c\c + 'A' - 11
			Case 37 To 62 : *c\c + 'a' - 37
			Case '.' ;do nothing
			Default : *c\c = '?'
		EndSelect
		*c + SizeOf(Character)
	Wend
	
	ProcedureReturn out
EndProcedure

Define unkomprimiert.s = "12345678901234567890"
Define komprimiert.s = Base_Convert(unkomprimiert, 10, 62, 100)
Define dekomprimiert.s = Base_Convert(komprimiert, 62, 10, 100)
Antworten