C言語のブール配列パズル:ループや条件分岐なしで配列の全要素を0にする方法
C言語のブール配列パズルとは?
これは配列を使った有名なパズルです。2つの要素を持つ整数型配列のすべての要素を0に変更することが課題となります。ただし、配列の片方の要素は必ず0であり、もう片方の要素は0である場合も、0以外の場合もあります。
このパズルを解くには、プログラムが0以外の要素を見つけ出し、それを0に書き換える必要があります。
パズルを解くための制約条件
このブール配列パズルを解く際には、以下の厳しい制約を守らなければなりません。
- 許可されているのは補数(complement)演算のみで、その他の演算は使用できません。
- ループ文や条件分岐文(if文など)は使用禁止です。
- 直接代入(a[0] = 0 のような書き方)も禁止されています。
一見すると不可能に思えますが、配列の添字(インデックス)自体を工夫して使うことで、これらの制約を満たしながら解くことができます。
ブール配列パズルを解くプログラム
以下がその解答コードです。ポイントは a[ a[1] ] = a[ !a[1] ]; の一行です。論理否定演算子 ! を使うことで、0と1を入れ替えた添字を作り出しています。
#include <iostream>
using namespace std;
void makeZero(int a[2]) {
a[ a[1] ] = a[ !a[1] ];
}
int main() {
int a[] = {1, 0};
makeZero(a);
cout<<"arr[0] = "<<a[0]<<endl;
cout<<"arr[1] = "<<a[1];
return 0;
}
実行結果
arr[0] = 0 arr[1] = 0
なぜこのコードで動作するのか
このトリックの仕組みを整理してみましょう。少なくとも片方の要素が必ず0であるという前提が鍵になります。
- a[1] が 0 の場合:
a[a[1]]はa[0]を指し、a[!a[1]]はa[1](値は0)を指します。したがってa[0] = 0となり、両方の要素が0になります。 - a[1] が 1 の場合: このとき
a[0]は必ず0です。a[a[1]]はa[1]を指し、a[!a[1]]はa[0](値は0)を指すため、a[1] = 0となり、やはり両方が0になります。
このように、どちらのケースでも配列全体が0に初期化されるのです。
否定演算を使わない別の解法
上記の方法以外にも、否定演算(negation)を一切使わない次のような解法があります。
a[ a[1] ] = a[ a[0] ];
こちらも同じ原理で動作します。a[0] と a[1] のうち片方は必ず0であるため、代入元と代入先の添字が自動的に適切な要素へと切り替わり、結果的に両方の要素が0になります。
配列の添字に式を渡せるC/C++の柔軟性を活かした、非常にエレガントなパズルといえるでしょう。
-
C#の多次元配列とは?2次元配列の宣言方法と使い方を実例付きで解説
C#では、多次元配列を扱うことができます。int型の2次元配列は、次のように宣言します。int[] a;多次元配列の中で最もシンプルな形式が2次元配列です。2次元配列とは、1次元配列を要素として持つ配列、すなわち「配列の配列」のような構造をイメージすると分かりやすいでしょう。例えば、次の図は3行4列の2次元配列を表しています。多次元配列の使用例ここからは、実際にC#で多次元配列を操作するサンプルコードを見ていきましょう。以下の例では、5行2列の2次元配列を宣言・初期化し、入れ子になったforループですべての要素を出力します。using System; namespace ArrayApplic
-
Pythonで学ぶ畳み込み(Convolution)の基礎:画像から特徴を抽出する仕組みと実装
本記事では、Python 3.x(またはそれ以前のバージョン)における「畳み込み(Convolution)」について解説します。畳み込みは、ニューラルネットワークや画像の特徴抽出において中心的な役割を果たす基本的な操作です。推奨環境 − Jupyter Notebook前提条件 − NumPy および Matplotlib がインストール済みであることインストール方法必要なライブラリが未インストールの場合は、以下のコマンドで導入できます。>>> pip install numpy >>> pip install matplotlib畳み込みとは畳み込みとは、