-
Pythonで解く「Kプレフィックス」問題:累積和を使って最大インデックスを効率的に求める方法
問題の概要 数値のリスト nums と整数 k が与えられたとき、「nums[0] + nums[1] + ... + nums[i] ≤ k」という条件を満たす最大のインデックス i を求めるのがこの問題です。条件を満たす i がひとつも存在しない場合は、-1 を返します。 たとえば、nums = [4, -7, 5, 2, 6]、k = 5 という入力の場合、答えは 3 になります。これは、先頭から nums[3] までを足すと 4 + (-7) + 5 + 2 = 4 となり、k 以下だからです。しかし最後の要素まで加えると合計が k を超えてしまうため、有効な最大インデックスは 3
-
Pythonでソート済みリストの隣接要素間の最大ギャップを求める方法
はじめに本記事では、数値のリスト nums が与えられたとき、そのリストをソートした状態における隣接する2つの要素の差(ギャップ)の中で最も大きい値を求める方法を解説します。例えば、入力が [5, 2, 3, 9, 10, 11] の場合を考えてみましょう。このリストを昇順にソートすると [2, 3, 5, 9, 10, 11] となり、隣接要素同士の差はそれぞれ「1, 2, 4, 1, 1」になります。したがって、最大のギャップは 5 と 9 の間の 4 となり、出力は 4 です。解決のアプローチこの問題は以下の手順で解くことができます。まず、リスト nums を昇順にソートします。隣接する
-
Pythonで最大値が2番目に大きい値の2倍を超えるか判定する方法
数値のリストが与えられたとき、そのリスト内の最大値が2番目に大きい値の2倍よりも大きいかどうかを判定する問題を考えてみましょう。 例を挙げると、リストが [3, 9, 6] の場合、最大値は9ですが、2番目に大きい値6の2倍である12より小さいため、結果は False になります。一方、リストが [6, 3, 15] の場合、最大値15は12(6の2倍)より大きいため、結果は True になります。 解法のアプローチ この問題は、リストを一度だけ走査しながら「最大値」と「2番目に大きい値」を追跡することで、効率的に解くことができます。具体的な手順は以下の通りです。 リストの要素数が2未満の場
-
Pythonで連続するk桁の数字の最大積を求める方法
2つの整数 num と k が与えられたとき、num の中で連続する k 桁の数字を取り出し、その積が最大となる組み合わせを求める問題を考えます。なお、num は必ず k 桁以上の数字を持つことが保証されています。 問題の例 例えば、num = 52689762、k = 4 の場合を考えてみましょう。このときの出力は 3024 になります。これは、4桁の連続した数字の組み合わせの中で「8 × 9 × 7 × 6 = 3024」が最大の積となるためです。 解法のアプローチ この問題は、以下の手順で解くことができます。 変数 largest を 0 で初期化します num を 10 の (k-1
-
Pythonでラテン方陣(ラテン方格)を生成する方法を解説
ラテン方陣とは?ラテン方陣(ラテン方格)とは、各行・各列に同じ数字が一度ずつ現れる、特殊なパターンを持つ行列のことです。まずはいくつかの例を見て、そのパターンを確認してみましょう。1 2 2 1 1 2 3 3 1 2 2 3 1 1 2 3 4 4 1 2 3 3 4 1 2 2 3 4 1上記の例からわかるように、ラテン方陣はさまざまなサイズで生成できます。しかし、これらの行列のパターンを注意深く観察すると、前の行の最後の数字が、次の行の最初の要素として現れるという規則性が見えてきます。これこそがラテン方陣に隠されたパターンです。今回は、入力 n に対してこのような行列を生成するプログ
-
Pythonで連結リスト(リンクリスト)の長さを求める方法
単方向連結リスト(片方向リンクリスト)が与えられたとき、その長さ(ノード数)を求めることを考えます。この連結リストは、next(次のノードへの参照)と val(ノードが保持する値)というフィールドを持っています。例えば、入力が [2 -> 4 -> 5 -> 7 -> 8 -> 9 -> 3] のような連結リストである場合、ノードは7個あるため、出力は 7 となります。解決のアプローチこの問題は、以下の手順で解くことができます。カウンタ変数 count を 0 で初期化する現在のノードが null(None)でない限り、以下を繰り返すcount を 1 増や
-
独自のボットネットを構築して学ぶ――セキュリティ研究者向けフレームワーク「BYOB」とは
「BYOB(Build Your Own Botnet)」は、セキュリティ研究者や開発者が基本的なボットネットを構築・運用できるように設計されたオープンソースのフレームワークです。毎年数百万台のデバイスに感染し、現代のボットネットを生み出している高度なマルウェアへの理解を深め、こうした脅威への対策能力を高めることを目的としています。開発者は、RAT(リモートアクセスツール)やC&C(Command & Control)サーバーをゼロから作成することなく、独自のコードや新しい機能を簡単に追加できます。 主な特徴 ディスクに何も書き込まない ― クライアントは一時ファイルすらディ
-
QRGenで作る悪意のあるQRコード:仕組みとペネトレーションテストへの活用
QRコードは、商品パッケージから航空券の搭乗券まで、あらゆる場面で自動スキャンされる機械可読データ形式です。このQRコードには、カスタムQRコードに組み込んだエクスプロイトによって一般的な脆弱性を突くことが可能です。ハッカーは「QRGen」というツールを使い、脆弱なデバイスを標的とした悪意のあるQRコードを作成します。QRコード攻撃が強力である理由は、人間がスキャンせずにQRコード内の情報を読み取ったり理解したりできない点にあります。コードの解読を試みたデバイスは、内部に仕込まれたエクスプロイトにさらされる可能性があります。人間は実際にスキャンする前に悪意のあるQRコードを見分けることができま
-
【Python】数値のすべての回転が素数かどうかを判定するプログラム
ある整数 n が与えられたとき、その桁を入れ替えてできるすべての回転数が素数であるかどうかを判定します。このような性質を持つ数は「循環素数(circular prime)」として知られています。 例えば、入力が n = 13 の場合を考えてみましょう。13 自体が素数であり、桁を入れ替えた 31 も素数であるため、出力は True になります。 解決のアプローチ この問題は、以下の手順で解くことができます。 数値 n を文字列に変換します。 n の桁数と同じ回数だけループ処理を行います。 現在の n が素数でなければ、False を返します。 素数であれば、先頭の桁を取り出して末尾に移動し
-
Pythonで単語リスト内の異なる回転グループの数を求めるプログラム
問題の概要 文字列には、そのすべての一意な回転をまとめた「回転グループ」が存在するとします。たとえば入力が 567 の場合、この文字列は 675 や 756 に回転でき、これらはすべて同じ回転グループに属します。 ここで、文字列のリスト words が与えられたとき、各単語を回転グループごとに分類し、グループの総数を求める必要があります。 たとえば、words = [xyz, ab, ba, c, yzx] の場合、出力は 3 になります。これは次の3つの回転グループが存在するためです。 [xyz, yzx] [ab, ba] [c] 解法のアプローチ この問題を解くために、以下の手順に
-
Pythonでランレングス符号化された文字列をデコードするプログラム
ランレングス符号化とはランレングス符号化(Run-Length Encoding、RLE)は、文字列を高速かつシンプルに圧縮できる手法として広く知られています。その基本的な考え方は、「連続して繰り返される文字を、繰り返し回数と文字のペアとして表現する」というものです。例えば、文字列 BBBBAAADDCBB の場合、Bが4回、Aが3回、Dが2回、Cが1回、Bが2回続いているため、4B3A2D1C2B とエンコードされます。本記事では、この逆の処理、すなわちエンコードされた文字列を受け取り、元の文字列へと復元(デコード)するPythonプログラムを解説します。問題の定義ランレングス符号化された文
-
Pythonで文字列をランレングス符号化(RLE)するプログラムの書き方
文字列 s が与えられたとき、これをランレングス符号化(Run-Length Encoding)と呼ばれる手法でエンコードすることを考えます。 ランレングス符号化は、文字列を高速かつシンプルに圧縮できる手法の一つです。基本的なアイデアは、「連続して繰り返される同じ文字を、連続回数(カウント)+その文字というペアに置き換える」というものです。 例えば、入力が s = BBBBAAADDCBB の場合、出力は 4B3A2D1C2B となります。これは「Bが4個、Aが3個、Dが2個、Cが1個、Bが2個続いている」という意味を表しています。 アルゴリズムの手順 この問題は、以下の手順で解くことができ
-
Pythonで隣接する異なるビットを削除した後の最短文字列の長さを求めるプログラム
2進文字列 s が与えられたとき、隣り合う2文字が異なる場合に限り、そのペアを削除できるものとします。この操作は何度でも繰り返し実行でき、最終的に得られる文字列のうち最も短くなるときの長さを求めるのがこの問題です。 例えば、入力が s = 1100011 の場合、答えは 1 になります。まず「10」を削除して「10011」にし、さらに「10」を削除して「011」とし、最後に「01」を削除すれば、残るのは「1」だけになるからです。 アプローチ:スタックを活用する この問題は、スタック(stack)を使うことで効率的に解けます。手順は以下のとおりです。 新しいリスト(スタック)を用意します。 文
-
Pythonで、部分リストを並べ替えるだけでリスト全体が昇順にソートされる最短の範囲を見つける方法
数値のリスト nums が与えられたとき、その一部を並べ替えるだけでリスト全体が昇順にソートされるような、最短の部分リスト(サブリスト)の長さを求める問題について解説します。 問題の例 たとえば、入力が nums = [1, 2, 5, 4, 9, 10] の場合、出力は 2 になります。これは、部分リスト [5, 4] を並べ替えるだけで、リスト全体が [1, 2, 4, 5, 9, 10] という昇順の状態になるためです。 解き方のアルゴリズム この問題は、次の手順で解くことができます。 f := -1、l := -1 として初期化する lst := リスト nums をソートしたコ
-
Pythonで最も近い人から少なくともkの距離を確保して立てるかどうかを判定するプログラム
問題の概要文字列 s と整数 k が与えられます。文字列の各文字は、空きスペースを表すドット(.)か、人がいる位置を表す「x」のどちらかです。このとき、最も近い人との距離が少なくとも k 以上になるような立ち位置を選べるかどうかを判定します。なお、隣接するインデックス間の距離は 1 とします。例えば、s = "x...x.."、k = 2 の場合、答えは True になります。s[2] または s[6] の位置に立てば、最も近い人との距離がちょうど 2 になるからです。解法のアプローチこの問題は、次の手順に従って解くことができます。文字列 s の中で最初の「x」の位置を p
-
Pythonでソート後に正しい位置にある要素の数をカウントする方法
問題の概要数値のリスト nums が与えられたとき、そのリストをソートした場合に元の位置から動かない要素(正しいインデックスに配置される要素)がいくつあるかを求めるプログラムをPythonで作成します。例えば、入力が [2, 8, 4, 5, 11] の場合を考えてみましょう。このリストを昇順にソートすると [2, 4, 5, 8, 11] になります。比較すると、先頭の「2」と末尾の「11」はソート前後で同じ位置に留まっています。したがって、出力は 2 となります。解決のアプローチこの問題は、以下の手順でシンプルに解くことができます。リスト nums をソートした新しいリスト s を作成する
-
Pythonで複数のメールボックスから重要なメールをラウンドロビン順に抽出するプログラム
本記事では、複数のメールボックスからジャンクメールを除外し、重要なメールだけを1つのリストにまとめるPythonプログラムを紹介します。問題の概要複数のメールボックス(リスト)が与えられます。各メールボックスには文字列のリストが格納されており、それぞれの文字列は次のいずれかを表します。「J」: ジャンクメール(Junk)「P」: 個人メール(Personal)「W」: 仕事メール(Work)最初のメールボックスから順にラウンドロビン方式(各メールボックスを1通ずつ順番に巡回する方式)でメールを取り出し、「J」を除外した結果を1つのリストとして返すのが目的です。入力例と出力例たとえば、入力が以下
-
Pythonでリストを左右から順に圧縮し、1つの要素になるまで変形するプログラム
数値のリスト nums が与えられたとき、リストの左端と右端から交互に隣接する要素同士を足し合わせて圧縮(スクイーズ)し、要素が1つだけ残るまでこの操作を繰り返します。そして、各ステップにおけるリストの状態をすべて返すのが目的です。たとえば、入力が nums = [10, 20, 30, 40, 50, 60] の場合、出力は次のようになります。[ [10, 20, 30, 40, 50, 60], [30, 30, 40, 110], [60, 150], [210]]解決のための手順この問題は、次のアルゴリズムで解くことがで
-
Pythonでリストが厳密に増加・減少しているかを判定するプログラムの作成方法
数値のリストが与えられたとき、そのリストが厳密に増加しているか、あるいは厳密に減少しているかどうかを判定することを考えてみましょう。 ここで「厳密に増加」とは、すべての要素が互いに異なり、各要素が必ず直前の要素より大きい状態を指します。たとえば、入力が nums = [10, 12, 23, 34, 55] の場合、どの要素も重複しておらず、前の要素より常に大きいため、出力は True となります。 解決のための手順 この問題は、以下のステップに沿って解くことができます。 nums のサイズが 2 以下である場合は True を返します。 nums 内に重複した要素が存在する場合は Fal
-
【Python】文字列として表現された2つの数値を加算して文字列で返す方法
2つの文字列 S と T が与えられ、それぞれが整数を表しているとします。この2つの数値を加算し、その結果を同じく文字列として返す必要があります。 例えば、入力が 256478921657 と 5871257468 の場合、出力は 262350179125 になります。これは、256478921657 + 5871257468 = 262350179125 となるためです。 解決の手順 この問題は、以下のステップで解決できます。 S と T を文字列から整数に変換する 2つの整数を加算する(ret = S + T) 結果の ret を文字列に変換して返す Pythonでは int() 関数