質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

1310閲覧

C++でcodelic(プログラミングサイト)のLesson5_4のMinAvgTwoSliceの問題の正解を参考に書いたコードで正解が出せない。

ratera

総合スコア54

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2021/11/30 02:29

編集2021/11/30 02:37

codelic(プログラミングサイト)のLesson5_4のMinAvgTwoSliceの問題正解したコードを参考に書き下したコードで正解が出せません。
答えに違いが出る理由を教えてほしいです。

このような場合は入力値をベースにデバッグするのが筋ですが、入力値がわからずどのように原因を探ればよいのか詰めの甘い状態です。宜しくお願いします。

問題

codelic(プログラミングサイト)のLesson5_4のMinAvgTwoSliceの問題

解き方のロジック補足

  • 解き方は、2つまたは3つの連続する配列の平均値を測る。
  • 4つ以上連続する配列においては、2つ連続または3つ連続の場合の方が必ず小さくなるため、平均値を確認する必要がない

入力と期待結果

明確なインプットはわかっていません。
以下のlarge_onesのケースだけ、誤った期待値が出力されています。(正答率90%です。)

イメージ説明

比較すべき箇所のコードの抜粋

以下、 正解コード抜粋です

C++

1 //2・3つの連続する配列の平均値を求め、最小値を発見した場合に格納する。 2 for (int i=0; i<A.size()-2; i++){ 3 float v1 = (float)(A[i]+A[i+1]+A[i+2])/3.0; 4 float v2 = (float)(A[i]+A[i+1])/2.0; 5 if(min>v1 || min>v2) { 6 min=std::min(v1,v2); 7 mi=i; 8 } 9 } 10 //2要素で、配列の最後を足した場合のケースが漏れているため、追加している。 11 if (min> (((A[A.size()-1]+A[A.size()-2])/2.0))) 12 { 13 return (A.size()-2); 14 }

以下、不正解コード抜粋です

C++

1 //3つの連続する配列の平均値を求める。配列のサイズが2以下の場合は処理を行わないようにする 2 if (A.size()>2){ 3 for (int i=0; i<A.size()-2; i++){ 4 float v1 = (float)(A[i]+A[i+1]+A[i+2])/3.0; 5 if(min > v1) { 6 min=v1; 7 mi=i; 8 } 9 } 10 } 11 //2つの連続する配列の平均値を求める。 12 for (int i=0; i<A.size()-1; i++){ 13 float v2 = (float)(A[i]+A[i+1])/2.0; 14 if(min > v2) { 15 min=v2; 16 mi=i; 17 } 18 }

コード全体

以下、正解コードです

C++

1//回答url:https://app.codility.com/demo/results/trainingJ2X3EM-VKH/ 2// 3// Task Score: 100% 4// Correctness: 100% 5// Performance: 100% 6//Detected time complexity: 7 8// #pragma GCC target("avx2") 9// #pragma GCC optimize("O3") 10// #pragma GCC optimize("unroll-loops") 11#define _GLIBCXX_DEBUG//配列外参照のデバッグ用 12 13#include <bits/stdc++.h> 14#define rep(i, n) for (int i = 0; i < (n); ++i) 15#define rep1(i, n) for (int i = 1; i <= (n); ++i) 16using namespace std; 17using ll = long long; 18using P = pair<int, int>; 19 20//2 <= int N <~10^6 21//-10^5 <= int A[i] <=10^5 22//Aはペア型ではなかった。 0 ≤ P < Q < N 23 //A pair of integers (P, Q), such that 0 ≤ P < Q < N 24 25//速度重視だと、こちらのコードの方が若干早いhttps://youtu.be/Xu_hTjFAauk=508 26//解き方は、2つまたは3つの連続する配列の平均値を測る。 27//4つ連続する場合においては、2つ連続または3つ連続の場合の方が必ず小さくなるため、平均値を確認する必要がない 28int solution(vector<int> &A) { 29 float min=INT_MAX; 30 int mi=0; 31 32 for (int i=0; i<A.size()-2; i++){ 33 float v1 = (float)(A[i]+A[i+1]+A[i+2])/3.0; 34 float v2 = (float)(A[i]+A[i+1])/2.0; 35 if(min>v1 || min>v2) { 36 min=std::min(v1,v2); 37 mi=i; 38 } 39 } 40 //2要素で、配列の最後を足した場合のケースが漏れているため、追加している。 41 if (min> (((A[A.size()-1]+A[A.size()-2])/2.0))) 42 { 43 return (A.size()-2); 44 } 45 return mi; 46} 47 48int main(){ 49 vector<int> B={4,2,2,5,1,5,8}; 50 cout << solution(B) << endl; 51 return 0; 52 vector<int> c={-1,-1,0,1,1,-1,-1}; 53 cout << solution(c) << endl; 54 return 0; 55}

以下、不正解コードです

C++

1//回答url: 2// 3// Task Score: 100% 4// Correctness: 100% 5// Performance: 100% 6//Detected time complexity: 7 8#pragma GCC target("avx2") 9#pragma GCC optimize("O3") 10#pragma GCC optimize("unroll-loops") 11// #define _GLIBCXX_DEBUG//配列外参照のデバッグ用 12 13#include <bits/stdc++.h> 14#define rep(i, n) for (int i = 0; i < (n); ++i) 15#define rep1(i, n) for (int i = 1; i <= (n); ++i) 16using namespace std; 17using ll = long long; 18using P = pair<int, int>; 19 20//2 <= int N <~10^6 21//-10^5 <= int A[i] <=10^5 22//Aはペア型ではなかった。 0 ≤ P < Q < N 23 //A pair of integers (P, Q), such that 0 ≤ P < Q < N 24 25//速度重視だと、こちらのコードの方が若干早いhttps://youtu.be/Xu_hTjFAauk=508 26//解き方は、2つまたは3つの連続する配列の平均値を測る。 27//4つ連続する場合においては、2つ連続または3つ連続の場合の方が必ず小さくなるため、平均値を確認する必要がない 28int solution(vector<int> &A) { 29 float min=INT_MAX; 30 int mi=0; 31 32 if (A.size()>2){ 33 for (int i=0; i<A.size()-2; i++){ 34 float v1 = (float)(A[i]+A[i+1]+A[i+2])/3.0; 35 if(min > v1) { 36 min=v1; 37 mi=i; 38 } 39 } 40 } 41 for (int i=0; i<A.size()-1; i++){ 42 float v2 = (float)(A[i]+A[i+1])/2.0; 43 if(min > v2) { 44 min=v2; 45 mi=i; 46 } 47 } 48 return mi; 49} 50 51int main(){ 52 vector<int> B={4,2,2,5,1,5,8}; 53 cout << solution(B) << endl; 54 return 0; 55 vector<int> c={-1,-1,0,1,1,-1,-1}; 56 cout << solution(c) << endl; 57 return 0; 58}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

episteme

2021/11/30 02:33

どんな問題を解いたコードなのかわからん。
ratera

2021/11/30 02:35

ご指摘ありがとうございます。追加しました。 お手数おかけしてすみません。
guest

回答2

0

ベストアンサー

問題によれば、平均が同じになったとき、一番若いindexを返す必要があります。不正解コードではそうならないことがありますね。
たとえば、3平均のmin, miが0, 100で、2平均のmin,miが0,10の時とかです。

投稿2021/11/30 03:19

matukeso

総合スコア1681

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ratera

2021/11/30 03:54

ありがとうございます。理解できました! その筋で考えてみてはいたのですが、早とちりで問題がないと誤った判断をしてしまっておりました。 貴重なお時間をいただき、ありがとうございます! 【解決したお話】 ・計算中の値が、(3平均のmin, miが0, 100で、2平均のmin,miが0,10の時など)最小値は同じだが、最小となるインデックスが異なる場合に事象が発生する。 ・不正解コードだと、3平均だけを扱った場合にmi(最小のインデックス)が100で更新され、2平均のmiの10で更新されるべき箇所が、最小値が同じ0であるため更新されずにバグとなる。
guest

0

該当のロジックを追加し、ケースpathすることを確認できました。

for (int i=0; i<A.size()-1; i++){ float v2 = (float)(A[i]+A[i+1])/2.0; if(((min==v2) && (mi>i)) || (min > v2)) { //NG:このロジックに要注意 min=v2; mi=i; } }

投稿2021/11/30 04:47

編集2021/11/30 04:49
ratera

総合スコア54

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問