algorytm sprawdzający wartość średnią z sumy sąsiadów w nieskonczonym ciągu

0

Witam. Ucze się do kolokwium i napotkałem takie zadanie:

Proszę napisać program, który wczytuje wprowadzany z klawiatury ciąg liczb naturalnych
zakończonych zerem stanowiącym wyłącznie znacznik końca danych.
Program powinien wypisać te elementy ciągu które są równe średniej arytmetycznej z 4 najbliższych
sąsiadów. Na przykład dla ciągu: 2,3,2,7,1,2,4,8,5,2,2,4,3,9,5,4,0 powinny zostać wypisane
podkreślone liczby. Można założyć, że w ciągu znajduje się co najmniej 5 elementów.

Jak je rozwiązać nie używając list, kolejek itp. W takim "rasowo czystym" C.
Proszę o pomoc, pozdrawiam1

0

nie rozumiem co ma byc wypisane

1

Wczytujesz elementy do tablicy (jak chcesz się postarać możesz wszystko robić na tablicy 5-elementowej), dla każdego elementu od elementu 3. do 3. od końca wyliczasz średnią i wypisujesz go jeśli jest jej równy.

0

Dzieki za odpowiedź przede wszystkim.
Hmmm. Dobry pomysł tylko nie mam pojęcia jak to zaimplementować.
Musze przesuwać te elementy co jedną wczytaną liczbę?
I jak obsłużyć początkowe 2 oraz końcowe 2?

1

Obsłuż je osobno lub wcale, ciężko wywnioskować z parametrów zadania które należy wykonać.

3

Możesz zastosować bufor cykliczny, z racji, że mean([a, b, c, d, e]) == mean([e, a, b, c, d]). Czyli masz coś takiego:

buf[0..4] - bufor
i = 0 - pozycja w buforze

buf[0] = read_num()
buf[1] = read_num()
buf[2] = read_num()
buf[3] = read_num()
buf[4] = read_num()

-- zakładamy, że 0 nie pojawi się wcześniej niż jako 6 liczba

loop
  print(mean(buf))
  buf[i] = read_num()
  if buf[i] == 0 then break
  i = (i + 1) mod 5
end
0

Po długiej walce poległem. Nie mam pojęcia co tu jest źle...
Ktos ma jakiś pomysł?
Czuje, że robie to na około jakoś :/ ale nie umiem za bardzo programować


#include <iostream>

using namespace std;

void checkStart(int tab[]){
	double srednia = (tab[1]+tab[2]+tab[3]+tab[4])/4.0;
	if(srednia == tab[0]){
		cout << "znalazlem: " << tab[0] << endl;
	}

	srednia = (tab[0]+tab[2]+tab[3]+tab[4])/4.0;
	if(srednia == tab[1]){
		cout << "znalazlem: " << tab[1] << endl;
	}
}

void checkEnd(int tab[]){
	double srednia = (tab[1]+tab[2]+tab[3]+tab[0])/4.0;
	if(srednia == tab[4]){
		cout << "znalazlem: " << tab[4] << endl;
	}

	srednia = (tab[0]+tab[2]+tab[1]+tab[4])/4.0;
	if(srednia == tab[3]){
		cout << "znalazlem: " << tab[3] << endl;
	}
}

void check(int tab[], bool shift){
	double srednia = (tab[0]+tab[1]+tab[3]+tab[4]) / 4.0;
	if(tab[2] == srednia)
		cout << "znalazlem: " << tab[2] << endl;

	if(!shift) return;

	for(int i = 0; i < 5-1; i++){
		tab[i] = tab[i+1];
	}

}

int main(){

	int tab[5];
	int n;
	int cnt = 0;
	while((cin >> n) && n != 0){
		cnt++;

		if(cnt > 5){
			tab[4] = n;
			check(tab, true);
			continue;
		}

		if(cnt <= 5/* && cnt >= 2*/){
			tab[cnt % 5] = n;
			if(cnt >= 2)
				check(tab, false);
		}
		
		if(cnt == 5){
			checkStart(tab);
		}
		
	}

	checkEnd(tab);

	return 0;
}
0

Ostatecznie wyszło mi coś takiego: (po paru h sprawdzania :/)
I to działa!. Dzięki za pomoc!


#include <iostream>

using namespace std;

void checkStart(int tab[]){
	double srednia = (tab[1]+tab[2]+tab[3]+tab[4])/4.0;
	if(srednia == tab[0]){
		cout << "   "  << tab[0] << endl;
	}

	srednia = (tab[0]+tab[2]+tab[3]+tab[4])/4.0;
	if(srednia == tab[1]){
		cout << "   "  << tab[1] << endl;
	}
}

void checkEnd(int tab[]){
	double srednia = (tab[1]+tab[2]+tab[3]+tab[0])/4.0;
	if(srednia == tab[4]){
		cout << "   "  << tab[4] << endl;
	}

	srednia = (tab[0]+tab[1]+tab[2]+tab[4])/4.0;
	if(srednia == tab[3]){
		cout << "   "  << tab[3] << endl;
	}
}

void check(int tab[]){
	double srednia = (tab[0]+tab[1]+tab[3]+tab[4]) / 4.0;
	if(tab[2] == srednia)
		cout << "   "  << tab[2] << endl;
}

void shift(int tab[]){
	for(int i = 0; i < 5-1; i++){
		tab[i] = tab[i+1];
	}
}

int main(){

	int tab[5]{};
	int n;
	int cnt = 0;
	while((cin >> n) && n != 0){
		if(cnt >= 5){
			shift(tab);
			tab[4] = n;
			check(tab);
			continue;
		}

		if(cnt < 5){
			tab[cnt % 5] = n;

			if(cnt == 4/*pierwsze 5*/){
				checkStart(tab);
			}
		}

		cnt++;
	}

	checkEnd(tab);

	return 0;
}
0
  1. Średnia nie musi się znajdować pośród Twoich liczb, może miałeś szukać mediany? Nie ma podkreśleń w oryginalnym poście, więc ciężko powiedzieć co chcesz.
  2. Ten kod to koszmar:
  • Po co liczysz średnią za każdym razem? Raz wystarczy.
  • Czemu masz 3 różne funkcje robiące de facto to samo?
  • Zamiast przesuwać wartości w buforze użyj bufora cyklicznego, który podałem wyżej.

Podam przykładowe rozwiązanie, ale by nie było za łatwo, masz je w Ruscie:

use std::io::{self, BufRead};

#[derive(Copy, Clone)]
struct CyclicBuffer {
    buf: [u32; 5],
    pos: usize,
}

fn insert(buf: &mut CyclicBuffer, val: u32) {
    buf.buf[buf.pos] = val;
    buf.pos = (buf.pos + 1) % 5;
}

fn mean(buf: &CyclicBuffer) -> f64 {
    let mut sum = 0.0;

    for &item in &buf.buf { sum += item as f64 }

    sum / 5.0
}

fn main() {
    let stdin = io::stdin();
    let stdin = stdin.lock();
    let mut lines = stdin.lines();

    let mut buffer = CyclicBuffer {
        buf: [0; 5],
        pos: 0,
    };

    for line in (0..5).flat_map(|_| lines.next()) {
        insert(&mut buffer, line.unwrap().trim().parse().unwrap());
    }

    println!("{}", mean(&buffer));

    for line in lines {
        let num = line.unwrap().trim().parse().unwrap();

        if num == 0 { return }

        insert(&mut buffer, num);
        println!("{}", mean(&buffer));
    }
}

Działa: https://ideone.com/02zdQv

A jeśli ma to być mediana to: https://ideone.com/2rjqPb

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