Seite 1 von 1
Vektor erstellen
Verfasst: Dienstag 22. November 2011, 18:35
von Python_Neuling
Hallo,
da ich mich mit Python noch nicht gut auskenne, verzweifle ich seit Tagen an folgender Aufgabe:
Ich soll einen Vektor (V1) mit Nullen und Einsen erstellen. V1 =
000010000010000. Nun soll ich aus V1 einen Vektor (V2) erstellen, der
folgende Eigenschaft hat: Jedes mal, wenn in V1 eine 1 ist, sollen vor
und hinter der 1 drei weitere 1en gesetzt werden. So dass V2 dann so
aussieht:
V1 = 0000 1 00000 1 0000 bzw. False False False False True usw.
[mein Script, was aus V1 V2 macht]
V2 = 0111 1 11111 1 1110 bzw. False True True True True usw.
Es wäre prima, wenn jemand eines Lösungsansatz parat hätte

Re: Vektor erstellen
Verfasst: Dienstag 22. November 2011, 18:43
von deets
So laeuft das hier nicht. Du sollst deine Hausaufgaben schon selbst machen. Wir helfen gerne - aber nur dann, wenn wir sehen, dass du dich selbst bemuehst, indem du deinen bestehenden Code hier postest (python-tags nicht vergessen...), zusammen mit konkreten Fragen und/oder Fehlerbeschreibungen.
Re: Vektor erstellen
Verfasst: Dienstag 22. November 2011, 18:57
von derdon
Wenn du die Lösung deinem Lehrer zeigst, wird er eh nicht glauben, dass es von dir kommt, weil du niemals so schrecklichen Code schreiben würdest
Code: Alles auswählen
>>> ''.join(d=="1"and"0001000"or d for d in "000010000010000")
'000000010000000000010000000'
Re: Vektor erstellen
Verfasst: Dienstag 22. November 2011, 19:05
von BlackJack
Die Hausaufgabe haben noch andere. Und einer davon hat sie vor ein paar Tagen hier erst von jemandem gelöst bekommen.
@derdon: Das ist keine Lösung für die Aufgabe.
Re: Vektor erstellen
Verfasst: Dienstag 22. November 2011, 19:06
von /me
Python_Neuling hat geschrieben:Es wäre prima, wenn jemand eines Lösungsansatz parat hätte

Lösungsansatz: Du könntest die Positionen ermitteln die eine '1' enthalten und dann anschließend jeweils den Teil davor und dahinter mit '111' überschreiben.
Re: Vektor erstellen
Verfasst: Dienstag 22. November 2011, 19:15
von derdon
BlackJack: Umso besser! Hab's auch gerade gemerkt, bei meinem Code wird ja nicht überschrieben.
Re: Vektor erstellen
Verfasst: Dienstag 22. November 2011, 19:25
von Hyperion
Interessant wäre noch zu wissen, ob V1 immer so lang ist oder er auch kürzer sein kann. Was passiert z.B. hiermit?
Re: Vektor erstellen
Verfasst: Dienstag 22. November 2011, 19:33
von /me
Hyperion hat geschrieben:Interessant wäre noch zu wissen, ob V1 immer so lang ist oder er auch kürzer sein kann. Was passiert z.B. hiermit?
Bei meinem schnell hingeknallten Code passieren damit gar schröckliche Dinge.

Re: Vektor erstellen
Verfasst: Dienstag 22. November 2011, 20:17
von Hyperion
Ich habe eine Lösung mittels `defaultdict` gefunden - da spielt dann ein "Übertreten" der Grenzen keine Rolle mehr, zudem erspart man sich das Slicing.
Re: Vektor erstellen
Verfasst: Dienstag 22. November 2011, 20:23
von BlackJack
Da zu den Randfällen nichts gesagt wurde, traue ich mich mal folgende Lösung in Assembler für den C64 zu präsentieren:
Code: Alles auswählen
!to "test.prg", cbm
ptr = $fa
chrout = $ffd2
strout = $ab1e
* = $c000
start lda #<vector
ldy #>vector
sta ptr
sty ptr+1
jsr strout
lda #13
jsr chrout
ldx #0
loop ldy #3
lda (ptr),y
beq done
cmp #"1"
bne +
ldx #7
+ cpx #0
beq ++
lda #"1"
dex
++ ldy #0
sta (ptr),y
inc ptr
bne loop
inc ptr+1
bne loop
done lda #<vector
ldy #>vector
jsr strout
lda #13
jmp chrout
vector !pet "00001001000000001000000", 0
Testlauf:
Code: Alles auswählen
JIFFYDOS V6.01 (C)1989 CMD
C-64 BASIC V2 38911 BASIC BYTES FREE
CYBERPUNX RETRO REPLAY 64KB - 3.8P
READY.
LOAD"TEST.PRG",8,1
SEARCHING FOR TEST.PRG
LOADING $C000 $C055
READY.
SYS49152
00001001000000001000000
01111111111001111111000
READY.
Der Randfall mit dem der Code nicht klar kommt, ist wenn innerhalb der ersten drei Zeichen schon eine "1" steht.
Re: Vektor erstellen
Verfasst: Dienstag 22. November 2011, 21:24
von problembär
Ein Versuch in C (schmerzhaft wie immer):
Code: Alles auswählen
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* convvec.c - Convert Vector, compile with:
gcc -Wall -Wextra -ansi -pedantic convvec.c -o convvec */
char *convertvector(char *vector, int width);
int main() {
char vector[16] = "000010000010000";
puts(vector);
puts(convertvector(vector, 3));
return 0;
}
char *convertvector(char *vector, int width) {
int i;
int u;
int ones[15];
int oneindex;
int tochange[15];
int tochangeindex;
int vectorlength;
char *vectorp;
oneindex = 0;
tochangeindex = 0;
vectorlength = strlen(vector);
for(i = 0; i < vectorlength; i ++) {
if(vector[i] == '1') {
ones[oneindex] = i;
oneindex++;
}
}
for(i = 0; i < oneindex; i++) {
for(u = 1; u <= width; u++) {
tochange[tochangeindex] = ones[i] + u;
tochangeindex++;
tochange[tochangeindex] = ones[i] - u;
tochangeindex++;
}
}
for(i = 0; i < tochangeindex; i++) {
vectorp = vector;
if(tochange[i] >= 0) {
vectorp += tochange[i];
*vectorp = '1';
}
}
return vector;
}
(Kann sein, daß man "vector" in main() besser als Zeiger auf char mit malloc() anlegen sollte; bin dabei immer etwas unsicher. Glücklicherweise nimmt Python einem solche Fragen ab.

)
Re: Vektor erstellen
Verfasst: Dienstag 22. November 2011, 23:07
von BlackJack
Eine C-Lösung die mit weniger lokalen Variablen und einem einzigen Durchlauf des Vektors auskommt *und* die Randfälle berücksichtigt!
Code: Alles auswählen
#include <iso646.h>
#include <stdio.h>
#define HALF_WIDTH 3
void set_ones(char *vector)
{
char c;
unsigned int i, n = 0;
for (i = 0; i < HALF_WIDTH and (c = vector[i]); ++i) {
if (c == '1') n = HALF_WIDTH + i + 1;
}
for (i = 0; (c = vector[i + HALF_WIDTH]); ++i) {
if (c == '1') n = HALF_WIDTH * 2 + 1;
if (n) {
vector[i] = '1';
--n;
}
}
while (n and vector[i]) {
vector[i++] = '1';
--n;
}
}
int main(void)
{
char vector[] = "00001001000000001000000";
puts(vector);
set_ones(vector);
puts(vector);
return 0;
}
Re: Vektor erstellen
Verfasst: Mittwoch 23. November 2011, 09:57
von problembär
@BlackJack: Schöner Code!
Re: Vektor erstellen
Verfasst: Mittwoch 23. November 2011, 17:08
von BlackJack
Hier noch einmal eine überarbeitete Assemblerfassung. Die alte war ja sozusagen die mittlere Schleife aus der C-Funktion. Die beiden anderen Schleifen sind jetzt dazu gekommen:
Code: Alles auswählen
.importzp ptr1
.export _set_ones
HALF_WIDTH = 3
;
; void __fastcall__ set_ones(char *vector);
;
.proc _set_ones
.code
sta ptr1
stx ptr1+1
ldx #0
ldy #$ff
bne L2
loop1: lda (ptr1),y
beq loop2
cmp #'1'
bne L2
tya
clc
adc #HALF_WIDTH + 1
tax
L2: iny
cpy #HALF_WIDTH
bne loop1
loop2: ldy #HALF_WIDTH
lda (ptr1),y
beq endloop2
cmp #'1'
bne @skip1
ldx #HALF_WIDTH * 2 + 1
@skip1: cpx #0
beq @skip2
dex
lda #'1'
ldy #0
sta (ptr1),y
@skip2: inc ptr1
bne loop2
inc ptr1+1
bne loop2
endloop2:
ldy #0
loop3: dex
bmi endloop3
lda (ptr1),y
beq endloop3
lda #'1'
sta (ptr1),y
iny
bne loop3
endloop3:
rts
.endproc
`ptr1` dient als Pointer auf/in den `vector`, `y` als Offset zu `ptr1` und das `n` aus der C-Funktion ist das X-Register.
Re: Vektor erstellen
Verfasst: Mittwoch 23. November 2011, 18:27
von problembär
Nunja, hier auch nochmal eine etwas veränderte Version meines C-Beispiels oben, auch wenn das immer noch etwas umständlich sein mag:
Code: Alles auswählen
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* convvec.c - Convert Vector, compile with:
gcc -Wall -Wextra -ansi -pedantic convvec.c -o convvec */
char *convertvector(char *vector, int width);
int main() {
/* char vector[] = "000010000010000"; */
char vector[] = "00001001000000001000000";
puts(vector);
puts(convertvector(vector, 3));
return 0;
}
char *convertvector(char *vector, int width) {
int i;
int u;
int vectorlength = strlen(vector);
int *ones = malloc(vectorlength - 1);
int oneindex;
int *tochange = malloc(vectorlength - 1);
int tochangeindex;
oneindex = 0;
tochangeindex = 0;
for(i = 0; i < vectorlength; i ++) {
if(vector[i] == '1') {
ones[oneindex] = i;
oneindex++;
}
}
for(i = 0; i < oneindex; i++) {
for(u = 1; u <= width; u++) {
tochange[tochangeindex] = ones[i] + u;
tochangeindex++;
tochange[tochangeindex] = ones[i] - u;
tochangeindex++;
}
}
for(i = 0; i < tochangeindex; i++) {
if(tochange[i] >= 0 && i < vectorlength) {
vector[tochange[i]] = '1';
}
}
return vector;
}
Der Zeiger "*vectorp" ist weg. Wenn ich einen C-String als Zeiger auf char hatte und den ändern wollte, hab' ich sonst einen zweiten Zeiger auf die Anfangsadresse gesetzt und bin mit diesem an die Stellen hin- und hergesprungen, die ich ändern wollte. So auch mit diesem "*vectorp". Grund für den zweiten Zeiger war, das man mit dem ersten immer noch die Anfangsadresse gespeichert hatte, die man ja brauchte, etwa um den String auszugeben. Na ja, das ist alles gar nicht nötig: Man kann C-Strings ja auch gleichzeitig als Arrays betrachten und Zeichen darin über z.B. vector[3] usw. ändern. Wieder was gelernt.
Die Dimensionierung der Arrays "ones" und "tochange" mit festen Zahlen (hier: 15) war natürlich nicht optimal. Jetzt also eine dynamische Dimensionierung mit malloc(). Hab' so noch nie ein int-Array dimensioniert. Scheint zu gehen ...
Über die Randfälle hatte ich mir zuvor auch schon Gedanken gemacht. Bei der Aufgabenstellung ist mir nicht klar, wie bei denen verfahren werden soll. Bei mir wird ja in "tochange" gespeichert, welche Stellen von "vector" geändert werden sollen. Hab' halt eine Bedingung eingebaut, daß nur dann die Änderung wirklich durchgeführt werden soll, wenn der in "tochange" gespeicherte Wert innerhalb der Länge von "vector" liegt. Sonst wird eben gar nichts gemacht. Weiß nicht, ob das der Aufgabenstellung entspricht.
Hab' jedenfalls dabei wieder ein, zwei Schritte in C gelernt. Bin da ja (wie man sieht) noch recht am Anfang. War also ganz hilfreich, die Hausaufgabe. Für mich jedenfalls.
Edit: [\code=c] scheint im Beitrag statt "&&" "&&" zu liefern?
Re: Vektor erstellen
Verfasst: Mittwoch 23. November 2011, 19:20
von EyDu
Das schreit doch schon fast nach dem Einsatz von zip:
Code: Alles auswählen
>>> example = [0,0,0,0,1,0,0,0,0,0,1,0,0,0,0]
>>> size = 3
>>> map(int, map(any, zip(*[([0]*size+example+[0]*size)[i:] for i in range(2*size+1)])))
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0]
problembär hat geschrieben:Edit: [\code=c] scheint im Beitrag statt "&&" "&&" zu liefern?
Das ist ein bekanntes Problem mit dem Codehighlighting.
Re: Vektor erstellen
Verfasst: Mittwoch 23. November 2011, 19:56
von BlackJack
@problembär: Du forderst mit `malloc()` mit an Sicherheit grenzender Wahrscheinlichkeit nicht genug Speicher an. Das funktioniert also nur solange nicht zu viele '1'en in `vector` sind. Wenn Du Speicher für `n` ``int``\s haben möchtest, dann musst Du ``n * sizeof(int)`` Bytes anfordern. Die ``- 1`` ist auch falsch. `ones` muss mindestens die Länge von `vector` haben, und `tochange` muss die Länge von `vector` plus zwei mal `width` haben um für den Fall gewappnet zu sein, dass der `vector` tatsächlich nur aus '1'en besteht.
Am Ende der Funktion solltest Du den dynamisch angeforderten Speicher auch wieder frei geben.
Wegen dem kaputten Syntax-Highlighter hatte ich ``iso646.h`` eingebunden, damit ich ``and`` anstelle von ``&&`` schreiben konnte. Das mache ich normalerweise nicht.
Edit: Man kann das auf dem C64 natürlich auch ganz traditionell in BASIC lösen:
Code: Alles auswählen
10 HW=3:V$="00001001000000001000000":LV=LEN(V$):PRINT V$
20 DIM V$(LV):FOR I=0 TO LV:V$(I)=MID$(V$,I+1,1):NEXT
30 N=0:FOR I=0 TO HW:IF V$(I)="1" THEN N=HW+1+I
40 NEXT
50 FOR I=0 TO LV-HW:IF V$(I+HW)="1" THEN N=HW*2+1
60 IF N>0 THEN V$(I)="1":N=N-1
70 NEXT
80 IF N=0 OR I=LV THEN 100
90 V$(I)="1":I=I+1:N=N-1:GOTO 80
100 FOR I=0 TO LV:PRINT V$(I);:NEXT:PRINT