Übung für Gelangweilte

Übersicht Sonstiges Smalltalk

Neue Antwort erstellen

ozzi789

Betreff: Übung für Gelangweilte

BeitragMi, Feb 22, 2012 10:36
Antworten mit Zitat
Benutzer-Profile anzeigen
Schreibt einen Code welcher alle Zahlen zwischen 0 und 9,999,999 findet welche
den gleichen Wert haben wie die Quersumme * Querprodukt

Beispiel:
135 = (1+3+5) (1·3·5)



Meine Lösung (noch nicht optimiert..)
Braucht mit B3D auf einer 2.4 GHZ CPU 79 Sekunden
Code: [AUSKLAPPEN]
Const max=9999999
maxlenstr$=max
maxlen=Len(maxlenstr$)


startingtime=MilliSecs()

For mainloop=0 To max
   val=0
   valm=1
   For innerloop=1 To maxlen
      temp$=mainloop
      temp$=Mid(temp$,innerloop,1)
      val=val+Int(temp$)
      valm=valm*Int(temp$)
      If valm>0 Then totvalm=valm
   Next
   If mainloop=val*totvalm
      Print "found ! "+mainloop
   EndIf
Next

finishingtime=MilliSecs()

Print "It took me: "+(finishingtime-startingtime)/1000+" seconds"

Input


Grüsse,
ozzi
0x2B || ! 0x2B
C# | C++13 | Java 7 | PHP 5
  • Zuletzt bearbeitet von ozzi789 am Mi, Feb 22, 2012 15:07, insgesamt einmal bearbeitet

Eingeproggt

BeitragMi, Feb 22, 2012 13:28
Antworten mit Zitat
Benutzer-Profile anzeigen
Juhu, Langeweile! Smile

Habs mal anders probiert:

BlitzBasic: [AUSKLAPPEN]
Const max=9999999
Const digits=7

Dim power_of_10(digits)
power_of_10(0)=1
For i=1 To digits
power_of_10(i)=power_of_10(i-1)*10
Next

start=MilliSecs()

For i=1 To max
val=0
valm=1
temp=i
do=False
For j=digits To 0 Step -1
num=temp/power_of_10(j)
If num<>0 Then do=True
If do Then
temp=temp-num*power_of_10(j)
val=val+num
valm=valm*num
EndIf
Next
If i=val*valm Then
Print "found ! "+i
EndIf
Next


Print "It took me: "+(MilliSecs()-start)/1000+" seconds"

Input

End


Auf meinem PC braucht dein Code 60sek, meiner 19 Smile Im Debugmode. Ohne geht Print scheinbar nicht? Seit wann das? Naja, verwende Print eh nie...
Einziger Schönheitsfehler an meiner Lösung: Die "do"-Variable erscheint mir überflüssig, aber ohne hab ichs nicht geschafft... da fehlts noch an der letzten "mathematischen Raffinesse" Wink

mfG, Christoph.

EDIT: Stimmt das wirklich dass es nur 135 und 144 gibt?
Gewinner des BCC 18, 33 und 65 sowie MiniBCC 9

ozzi789

BeitragMi, Feb 22, 2012 15:04
Antworten mit Zitat
Benutzer-Profile anzeigen
Print funktioniert immer oO


Lösung:
0 , 1 , 135 , 144
Quelle:
http://mathworld.wolfram.com/S...umber.html

0 fehlt bei dir als Lösung Wink
Edit: Meine Aufgabenstellung ist falsch... angepasst Embarassed


Was ist das mit dem power_of_10 ?
Check das nicht ganz Very Happy




Edit2:
Eine Variabelnzuweisung aus dem Loop nehmen = 10 Sekunden schneller Laughing
0x2B || ! 0x2B
C# | C++13 | Java 7 | PHP 5

Eingeproggt

BeitragMi, Feb 22, 2012 16:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Ok dann is die Lösung wenigstens richtig Smile (0 und 1 ist "trivial" Razz )
Und da du schon der zweite bist der meine Lösung nicht kapiert hier eine kleine Erklärung:

nehmen wir die Zahl 1234 als Beispiel.
Du arbeitest mit Stringfunktionen um die erste, zweite,... Stelle heraus zu nehmen. Ich wollte probieren ob es nicht schneller wäre, die einzelnen Stellen zu "errechnen". Dazu muss man nicht zaubern. Man muss doch eigentlich nur rechnen:
1234 / 1000 = 1
Soweit, so gut. Oweh, ich hab das gar nicht genau untersucht wie BB das macht... Embarassed ich ging davon aus dass einfach alles nach dem Komma weggeschmissen wird und nicht "gerundet" wird. Schlimmstenfalls müsste ein Floor her.
Zweite Stelle ist trickreich aber auch irgendwie logisch:
1234 - (1 * 1000) / 100 = 234 / 100 = 2
und so gehts dann weiter:
234 - (2 * 100) / 10 = 34 / 10 = 3
und letztendlich
34 - (3 * 10) / 1 = 4
Ich hoffe das Schema ist ersichtlich.Und die 1000, 100, 10 (und alle anderen Potenzen von 10) stecken in "power_of_10".

mfG, Christoph.
Gewinner des BCC 18, 33 und 65 sowie MiniBCC 9
  • Zuletzt bearbeitet von Eingeproggt am Mi, Feb 22, 2012 16:21, insgesamt einmal bearbeitet

ozzi789

BeitragMi, Feb 22, 2012 16:20
Antworten mit Zitat
Benutzer-Profile anzeigen
Ah, jetzt hats klick gemacht !
Coole Lösung Cool
0x2B || ! 0x2B
C# | C++13 | Java 7 | PHP 5

SpionAtom

Betreff: Ziffern aus Zahl extrahieren

BeitragMi, Feb 22, 2012 16:32
Antworten mit Zitat
Benutzer-Profile anzeigen
Ziffern rechnerisch aus einer Zahl zu extrahieren is easy:

BlitzBasic: [AUSKLAPPEN]
;Ziffern aus Zahl extrahieren

zahl = 1337

temp = zahl
While temp > 0
Print temp Mod 10 ;letzte Stelle anzeigen
temp = temp / 10 ;letzte Stelle "abschneiden"
Wend

WaitKey
End
os: Windows 10 Home cpu: Intel Core i7 6700K 4.00Ghz gpu: NVIDIA GeForce GTX 1080

ozzi789

BeitragMi, Feb 22, 2012 17:22
Antworten mit Zitat
Benutzer-Profile anzeigen
Wenn man es mal irgendwo aufgeschnappt hat vlt, ich zumindest bin jetzt nicht einfach so draufgekommen, bin auch nicht der hellste was Zahlen angeht Laughing
0x2B || ! 0x2B
C# | C++13 | Java 7 | PHP 5

Ana

BeitragMi, Feb 22, 2012 18:35
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich würde es so machen

BlitzMax: [AUSKLAPPEN]
Function Quersumme:Int(x:Int)
Local r:Int = 0
While x > 0
r = r + x Mod 10
x = x /10
Wend
Return r
End Function

Function Querprodukt:Int(x:Int)
Local r:Int = 1
While x > 0
r = r * (x Mod 10)
x = x/10
Wend
Return r
End Function
Local c:Int = 0

Local timer:Int = MilliSecs()
While c < 999999
If (c = Quersumme(c) * Querprodukt(c)) Then Print c
c = c + 1
Wend

Print "Zeit: " + (MilliSecs() - timer)


Jetzt hab ich es aber mit BMax gemacht, eventuell ist das deutlich schneller als BB, es braucht bei mir 212 Millisekunden

EDIT: Oh ich hab mir die lösungen erst nachher angesehen, ist natürlich genau der selbe ansatz wie von Spion, da war wer schneller ^.^
Don't only practice your art,
but force your way into its secrets,
for it and knowledge
can raise human to divine

SpionAtom

Betreff: Komplett

BeitragMi, Feb 22, 2012 19:20
Antworten mit Zitat
Benutzer-Profile anzeigen
Dann hier auch nochmal meine vollständige Lösung:

BlitzBasic: [AUSKLAPPEN]
Const max=9999999

startzeit = MilliSecs()
found = 0

For zahl = 1 To max

qs = 0 ;Quersumme
qp = 1 ;Querprodukt
temp = zahl
fail = False
While temp > 0 And (Not fail)
letzteZiffer = temp Mod 10
If letzteZiffer > 0 Then If zahl Mod letzteZiffer <> 0 Then fail = True
qs = qs + letzteZiffer
qp = qp * letzteZiffer
temp = temp / 10 ;letzte Stelle "abschneiden"
Wend
If Not fail Then
If zahl = qs * qp Then Text 0, 16 * found, zahl: found = found + 1
End If

Next

Text 0, GraphicsHeight() - 16, "Benötigte Zeit: " + (MilliSecs() - startzeit) + " Millisekunden"
WaitKey
End


Quersumme und Querprodukt kann man in derselben Schleife berechnen.
Außerdem ist ein notwendiges Kriterium, dass die einzelnen Ziffern die Zahl teilen, diese Überprüfung gibt auch noch nen kleinen Schub.

~563ms
os: Windows 10 Home cpu: Intel Core i7 6700K 4.00Ghz gpu: NVIDIA GeForce GTX 1080

Vertex

BeitragMi, Feb 22, 2012 20:14
Antworten mit Zitat
Benutzer-Profile anzeigen
BlitzBasic: [AUSKLAPPEN]
Const NUM_DIGITS = 7

Dim zahl(NUM_DIGITS - 1)

Local quersumme = 0
Local querprodukt = 0

Const QUERSUMME_END = 9 * NUM_DIGITS
Const QUERPRODUKT_END = 9^NUM_DIGITS

Const CODE_0 = 48 ; = Asc("0")

Local startTime = MilliSecs()

Local count = 0
While Not (quersumme = QUERSUMME_END And querprodukt = QUERPRODUKT_END)
If zahl(NUM_DIGITS - 1) = 10 Then ; Übertrag
For i = NUM_DIGITS - 1 To 1 Step -1
zahl(i) = 0
If zahl(i - 1) <> 9
zahl(i - 1) = zahl(i - 1) + 1
Exit
EndIf
Next
EndIf

quersumme = 0
querprodukt = 1
Local inQuerprodukt = False

For i = 0 To NUM_DIGITS - 1
quersumme = quersumme + zahl(i)
; Führende Nullen ignorieren
If inQuerprodukt = False And zahl(i) <> 0 Then inQuerprodukt = True
If inQuerprodukt = True Then querprodukt = querprodukt * zahl(i)
Next

If count = (quersumme * querprodukt) Then Print zahlToString()
count = count + 1
zahl(NUM_DIGITS - 1) = zahl(NUM_DIGITS - 1) + 1
Wend
Print "ready in " + (MilliSecs() - startTime) + " ms"

WaitKey

Function zahlToString$()
Local out$ = ""

Local start = 0
While zahl(start) = 0
start = start + 1
If start = NUM_DIGITS Then Return "0"
Wend

For i = start To NUM_DIGITS - 1
out = out + Chr(CODE_0 + zahl(i))
Next

Return out
End Function


ozzi789: 54000 ms
Ana: 154 ms (mit B3D)
SpionAtom: 738 ms
Vertex: 676 ms
vertex.dreamfall.at | GitHub

SpionAtom

BeitragMi, Feb 22, 2012 20:42
Antworten mit Zitat
Benutzer-Profile anzeigen
Möglicherweise liegts daran, dass Ana eine 9 vergessen hat Rolling Eyes

Erklär mal deine Vorgehensweise, Vertex!
os: Windows 10 Home cpu: Intel Core i7 6700K 4.00Ghz gpu: NVIDIA GeForce GTX 1080

Vertex

BeitragDo, Feb 23, 2012 2:39
Antworten mit Zitat
Benutzer-Profile anzeigen
Die Idee ist, allle Ziffern in einem Array zu halten, um schneller deren Summe und Produkt zu bilden.

Inkrementieren von zahl:
Das Array zahl ist ein 7-elementiges Array, wobei das i-te Element die i-te Ziffer in der Zahl darstellt.
Also zahl_0 * 10^6 + zahl_1 * 10^5 + ... + zahl_6 * 10^0.

Die Addition mit Eins in dem Array kann man sich an dieser Folge verdeutlichen:
Code: [AUSKLAPPEN]
00179497
00179498
00179499
00179500

Zu einem Übertrag kann es nur kommen, wenn die letzte Ziffer, also zahl_6, = 9 ist und dann Eins dazu addiert wird. Dann wird der Übertrag an zahl_5 weitergegeben. War zahl_5 zuvor = 9, dann muss ein neuer Übertrag an zahl_4 weitergegeben werden usw.
vertex.dreamfall.at | GitHub

BlitzMoritz

BeitragDo, Feb 23, 2012 9:30
Antworten mit Zitat
Benutzer-Profile anzeigen
Erstmal: Danke, ozzi, für dein "Quiz" Very Happy Bitte mehr davon, ich will nämlich auch 'mal raten und nicht nur Aufgabensteller sein.

Nun zu meiner Lösung mit einem sehr schnellen und umgekehrten Ansatz:
Warum Millionen von Zahlen durchgehen, die mindestens eine Null als Ziffer besitzen und von vorneherein ausgeschlossen sind (bis auf die triviale Lösung 0)? Warum aufwendig und wiederholt Quersumme und Querprodukt neu berechnen, wenn man umgekehrt aus Kombinationen der Ziffern 1 bis 9 alle relevanten Zahlen bilden und dabei schon im vorhinein Teile der Quersumme und des Querprodukts vorausberechnen und Strings, Potenzen etc. vermeiden kann:
BlitzMax: [AUSKLAPPEN]
SuperStrict

Const max_digits% = 7 'maximale Stellenanzahl (von 9.999.999)
Local time% = MilliSecs()

Print "Found: 0" 'Der Sonderfall 0
'(ansonsten darf die Null als Ziffer nie mehr vorkommen)

search(0, 0, 1, 0) 'Suche mit Startwerten beginnen...

Print "time = " + (MilliSecs() - time) + " ms"

Function search(digits%, sum%, product%, ten_number%)
'Die Funktionsargumente:
'digits: Anzahl der Stellen bzw. Ziffern
'sum: bisherige Quersumme
'product: bisheriges "Querprodukt"
'ten_number: bisherige "Zahl", mit 10 multiplziert

Local new_sum%, new_product%, new_number%
Local new_digits% = digits+1

If new_digits < max_digits Then 'falls kleiner als maximale Stellenanzahl

For Local d% = 1 To 9 'alle erlaubten Ziffern durchgehen

new_sum = sum + d 'Quersumme erweitern
new_product = product * d '"Querprodukt" erweitern
new_number = ten_number + d 'neue "Zahl" aus Zehnerzahl und Einerziffer

'Vergleich:
If new_sum * new_product = new_number Then Print "Found: " + new_number

'rekursiv fortschreiten:
search(new_digits, new_sum, new_product, 10 * new_number)

Next

Else

'(das Gleiche, nur ohne rekursiven Funktionsaufruf)
For Local d% = 1 To 9
new_sum = sum + d
new_product = product * d
new_number = ten_number + d
If new_sum * new_product = new_number Then Print "Found: " + new_number
Next

End If

End Function

... braucht auf meinem alten Rechner 37 ms, und bei euch? Razz

Vertex

BeitragDo, Feb 23, 2012 11:09
Antworten mit Zitat
Benutzer-Profile anzeigen
BlitzMoritz, sehr gut! Braucht nur 43 ms bei mir. Ein paar ms könnte man da sicher noch herausholen, wenn man die Endrekursion in eine Iteration umformt.
vertex.dreamfall.at | GitHub

Neue Antwort erstellen


Übersicht Sonstiges Smalltalk

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group