Przepisanie z wektora do innego wektora jego unikalnych elementów

0

Witam, mam jeden wektor z elementami losowymi typu [1,2,3,2,2,1,1,2,3,4,1] chciałbym, aby w jakiś krótki sposób funkcja przepisała wszystkie występujące elementy z tej tablicy do nowej i otrzymam wówczas wynik w postaci [2,3,4,0,0,0,0,0,0,0] (jedynki mają być pomijalne)
Zera w drugim wektorze to wartości domyślne, nie będą nadpisywane, jeśli unikalnych elementów nie będzie wystarczająco dużo, jeśli jednak liczba elementów unikalnych przekroczy 10, to niech funkcja się zatrzyma.
Chodzi mi o jakiś prosty algorytm, wielkości wektorów są dane i niezbyt wielkie (pierwszy 300 elementów, drugi 10).

Generalnie mam do dyspozycji tylko IF, CASE, FOR, WHILE, bo to jezyk SCL, ale najbardziej i tak interesuje mnie ogólny algorytm, bo problem pojawia się u mnie w momencie, gdy muszę sprawdzić czy element wystąpił o 2 wstecz.

Aha,
coś takiego napisałem sam

A=[1,2,3,4,5,2,2,3,4,2,1,1,...] % jakiś random z określonego zakresu o określonej długości
B=zeros(10,1)
k=0;
for i:1:300
 if k==11
    return
 end
 if k==1 && A(i)~=1
   B(k)=A(i)
   k++;
 elseif k>1 && B(k-1)~=A(i)
   B(k)=A(i)
   k++; 
 end
end

No i właśnie w momencie przy elseif nie jest sprawdzany warunek czy np (B(k-2) ~= A(i) dla k=2 itd.
Nie wiem jak przy rosnącym k sprawdzić wszystkie poprzednie elementy, bo nie może być sytuacji, w której na końcu dostanę wektor: [2,3,4,2,0,0,0,0,0,0], bo 3 byłą różna do aktualnej wartości 2.

Algorytm napisałem w matlabie, ale możecie napisać w czymkolwiek lub tylko jakąś idee, będę bardzo wdzięczny.
Nie chcę tworzyć kolosa, tylko coś zwięzłego.

0

Widzę dwa wydajne rozwiązania, jeden wrzucać elementy do hashmapy i wpisać do drugiej tablicy tylko te elementy, które występowały raz, lub posortować tablicę i wtedy sprawdzanie unikalności też będzie łatwe. Obydwa te rozwiązania mogą być jednak skomplikowane do implementacji w tym języku, z tego co znalazłem na google to o bibliotekę standardową z tymi funkcjami to ciężko. Ze względu na wielkość problemu (300 elementów) można się pokusić o prosty kwadratowy algorytm. Bierzesz po kolei elementy i idziesz z nimi po tablicy. Jeżeli element w tablicy jest taki sam jak ten, który wziąłeś, to przypisujesz jakąś specjalną wartość (oznaczającą, żeby tego elementu już nie brać), jak takiego powtórzenia nie znaleziono, to tę wartość można wpisać do drugiej tablicy.

0

no właśnie, pętla w pętli, ale cały czas coś źle układam

EDIT: pętla w pętli odpada

for 0 to 300
for 0 to 9
end
end

to już zbyt kosztowne obliczeniowo i czas wykonania przekracza dozwolone 150ms a powinno być znacznie mniej poniżej 100 najlepiej :/

0
 
//A - tablica
//n - rozmiar tablicy
int j = 0;
for(int i=0;i<n;i++)
{
    if(A[i] == 1)
         j++;
    else
         B[i-j] = a[i];
}
for(int i=n-j;j<n;j++)
    B[i] = 0; 

Pisane na szybko bez sprawdzenia ale wydaje mi się że powinno działać :)

0
 
//A - tablica danych
//B - tablica wynikowa
//n - rozmiar tablicy
int j = 0;
for(int i=0;i<n;i++)
{
    if(A[i] == 1)
         j++;
    else
         B[i-j] = a[i];
}
for(int i=n-j;i<n;i++)
    B[i] = 0; 

Pisane na szybko bez sprawdzenia ale wydaje mi się że powinno działać :)

0

wielkie dzięki :), lecz nadal coś nie tak, bo funkcja odnosi się do jakiegoś elementu tablicy, który nie istnieje, czy na pewno
for(int i=n-j;i<n;i++)
jest okey, skoro B ma tylko 10 elementów?

ok poprawiłem to n na 10, z tym, że efekt jest taki, że elementy sa dublowane tzn
[2,2,3,3,3,4,4,0,0,0,]
przydałoby się to ominąć :)

0

Skopiuj tablice najpierw a później tylko trzeba dopisać zera ale to już chyba dasz radę :)

int k=0;
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
if(A[i]==A[j])
k++;
else
A[j-k] = A[j];
}
n -= k;
k = 0;
}

0

SCL to Scilab? Dlaczego nie użyjesz funkcji unique?

0

mi coś takiego działa w matlabie, ale na sterowniku niestety ma tendencje do wysypywania się, ale jutro spróbuję zobaczyć dokładniej co jest grane, może zapomniałem o czyszczeniu wektora

% A - źródłowy wektor
% B - docelowy wektor
for i= 1:length(A)
    powt=1;
    if k==15
        return
    end
    for n = 1:k
        if B(n)==A(i)
            powt = 0;
        end
    end
    if powt == 1
        B(k)=A(i);
        k=k+1;
    end
      
end

w każdym razie mniej kosztowne obliczeniowo rozwiązania mile widziane :)

@lewuaza za dużo kosztu, całość musi się zamknąć w 150ms ( to jest cały cykl całego programu, sama funkcja zajmuje mniej, ale nie wiem ile dokładnie)a jak napisałem

for 0 to 300
 for 0 to 9 
 end
end

to jest już max a i tak za wiele :/

0
0x200x20 napisał(a):

SCL to Scilab? Dlaczego nie użyjesz funkcji unique?

SCL to język do wykorzystania w nowych sterownikach PLC Siemensa, oparty na składni Pascala

1 użytkowników online, w tym zalogowanych: 0, gości: 1