「ちりめんじゃこ」に潜む”あいつら”を好きなだけ探せるゲーム。「手」と「ピンセット」を切り替えながら、大量の「ちりめんじゃこ」のなかから、そうではないものを見つけていく
Source link
Views: 0
「ちりめんじゃこ」に潜む”あいつら”を好きなだけ探せるゲーム。「手」と「ピンセット」を切り替えながら、大量の「ちりめんじゃこ」のなかから、そうではないものを見つけていく
Source link
Views: 0
『デビル メイ クライ 5(Devil May Cry 5)』のSteam同時接続数が記事執筆時点での直近24時間で6,809人まで伸びています。
本作は、2019年3月にリリースされたスタイリッシュアクションゲームシリーズ最新作。2022年10月時点では、全世界売上が600万本を突破しています。
最高同時接続数は、SteamDBによると6.1年前の88,894人となっていますが、ここ一ヶ月は、同時接続数は多くても2,500人前後、直近1週間でみると1,500人前後となっていました。しかし、4月3日23時に急激に増加し、5,889人に。4月4日18時には、6,809人となっています。
Netflixでは、4月3日からアニメ「Devil May Cry」を配信。またSteamでは、最大75%オフの『デビル メイ クライ』FRANCHISE SALEを開催中。これらの影響により、同時接続人数が大幅に増加したようです。
『デビル メイ クライ 5』は、PC(Steam)/PS4/Xbox One向けに、『デビル メイ クライ 5 スペシャルエディション』が、PS5/Xbox Series X|S向けに発売中です。
Views: 0
アンケートではまず「推し活」をしているユーザーに対し、どのジャンルを応援しているかを調査。上位5項目は以下の通りです。
・アーティスト/ミュージシャン
・アイドル(国内・海外問わず)
・キャラクター・アニメ/漫画
・俳優/女優
・スポーツ選手/チーム
「推し活をしている方へ。推し疲れしてしまった経験はありますか?」という質問に対し、「ある 33%」「ない 67%」という結果に。
約3分の1のファンが推し疲れを経験していることが明らかになりました。
・推し活にお金がかかりすぎた
・自分の生活や仕事が忙しくなった
・推し活に時間がかかりすぎた
・情報や供給についていけなくなった
・SNSのファン同士のトラブルやマウント合戦
推し疲れは特に経済的負担と時間的制約が大きな要因となっているよう。
近年のグッズ展開の多様化やイベント・配信の増加が、ファンの負担増につながっている可能性も考えられます。
「推し疲れした後、推し活はどうなりましたか?」という質問への回答順位は以下の通りでした。
・推し活のペースを落とした
・別の趣味を見つけた
・少し休んでまた再開した
・推し活をやめた
・他の推しに乗り換えた
完全に離れるのではなく、ペースダウンや一時休止という形で対応する人が多い結果に。
「少し休んでまた再開した」と回答した方に「推し疲れから立ち直る、一番のきっかけは何でしたか?」と質問した結果は以下の通りでした。
・時間を置いた
・推しへの愛を再確認した
・推し活以外の趣味を楽しんだ
・ファン仲間と話をした
・推しの新しい供給があった
適度な距離感の確保や客観的な視点を持つことが、健全な推し活の継続につながるようです。
現代のファン文化における「推し疲れ」の実態が明らかになった今回の調査。
自分のペースを大切にしながら、無理なく楽しく推し活を続けるヒントが詰まった貴重なデータとなりました!
調査方法:「QR/バーコードリーダー・アイコニット」アプリ内アンケート
実施時期:2025年1月7日
有効回答者数:21,883人
※アンケート結果の出典元:「アイコニット・リサーチ」調べ
Views: 0
Rustは「安全な言語」として知られています。特にメモリ安全性の面では優れた言語設計が施されていますが、それだけですべての問題が解決するわけではありません。コンパイラは多くのバグを捕捉してくれますが検出できない落とし穴も存在します。
上記の記事にRustで安全なコードを書く際によく遭遇する落とし穴と、それらを避けるためのベストプラクティスが非常によくまとまっていました。いくつか紹介します。
Rustのコンパイラは優秀ですが、以下のような問題は検出できません:
unwrap
やexpect
の使用による意図しないパニックbuild.rs
スクリプトそれでは、よくある落とし穴とその対策を見ていきましょう。
整数のオーバーフローはよくある問題です。次のコードを見てみましょう:
// 良くない例:オーバーフローの可能性がある
fn calculate_total(price: u32, quantity: u32) -> u32 {
price * quantity // 大きな数値の場合、オーバーフローする可能性あり!
}
この例では、price
とquantity
が大きな値の場合、結果がオーバーフローする可能性があります。デバッグモードではパニックしますが、リリースモードではラップアラウンドします(値が最大値を超えると0から再度カウントを始める)。
// 良い例:チェック付き算術演算
fn calculate_total(price: u32, quantity: u32) -> Resultu32, ArithmeticError> {
price.checked_mul(quantity)
.ok_or(ArithmeticError::Overflow)
}
checked_mul
などのメソッドを使うと、オーバーフローが発生した場合にNone
を返してくれるので、適切にエラー処理ができます。
また、Cargo.toml
に以下を追加しておくとリリースビルドでもオーバーフローチェックが有効になるそうです。覚えておきたいですね:
[profile.release]
overflow-checks = true
as
を安易に使わない数値型の変換にはよくas
キーワードが使われますが、これは安全でない場合があります:
let x: i32 = 1000;
let y: i8 = x as i8; // 値が範囲外なので切り捨てられる!
この例では、i32
からi8
への変換で値が切り捨てられ、予期しない結果になります。
Rustには3つの主要な数値変換方法があります:
as
キーワード:便利だが安全でない(値が切り捨てられる可能性あり)From::from()
:データ損失のない変換のみ許可(拡大変換に最適)TryFrom
:変換が失敗する可能性がある場合にResult
を返す// 良い例:TryFromを使った安全な変換
use std::convert::TryFrom;
let x: i32 = 1000;
let y = i8::try_from(x).map_err(|_| "値が大きすぎます")?;
この方法なら、変換が失敗した場合にエラー処理ができます。
数値が特定の条件を満たす必要がある場合、単純なプリミティブ型ではなく、境界つき型を使いましょう。
// 良くない例:無制限の数値型
struct Product {
price: f64, // マイナスの可能性あり!
quantity: i32, // マイナスの可能性あり!
}
// 良い例:境界つき型
#[derive(Debug, Clone, Copy)]
struct NonNegativePrice(f64);
impl NonNegativePrice {
pub fn new(value: f64) -> ResultSelf, PriceError> {
if value 0.0 || !value.is_finite() {
return Err(PriceError::Invalid);
}
Ok(NonNegativePrice(value))
}
}
struct Product {
price: NonNegativePrice,
quantity: std::num::NonZeroU32, // 0以外の正の整数のみ
}
この方法では、不正な値を持つオブジェクトが作れなくなります。
get
メソッドを使う配列やベクトルへの直接のインデックスアクセスは危険です:
let arr = [1, 2, 3];
let elem = arr[3]; // 範囲外アクセスでパニック!
get
メソッドでオプション値を返すlet arr = [1, 2, 3];
if let Some(elem) = arr.get(3) {
println!("4番目の要素: {}", elem);
} else {
println!("4番目の要素はありません");
}
split_at
よりsplit_at_checked
を使うスライスを分割する際も同様に注意が必要です:
let arr = [1, 2, 3];
let (left, right) = arr.split_at(4); // 範囲外でパニック!
let arr = [1, 2, 3];
match arr.split_at_checked(3) {
Some((left, right)) => println!("分割成功: {:?} と {:?}", left, right),
None => println!("インデックスが範囲外です")
}
文字列などのプリミティブ型をそのまま使うと、バリデーションが困難になります:
// 良くない例:制限のないString型
fn authenticate_user(username: String) {
// ユーザー名が空かも?特殊文字が含まれているかも?
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct Username(String);
impl Username {
pub fn new(name: &str) -> ResultSelf, UsernameError> {
if name.is_empty() {
return Err(UsernameError::Empty);
}
if name.len() > 30 {
return Err(UsernameError::TooLong);
}
if !name.chars().all(|c| c.is_alphanumeric() || c == '_') {
return Err(UsernameError::InvalidCharacters);
}
Ok(Username(name.to_string()))
}
pub fn as_str(&self) -> &str {
&self.0
}
}
fn authenticate_user(username: Username) {
// ユーザー名は常に有効!
}
この方法なら、関数に渡される時点で値が有効であることが保証されます。
フィールドの組み合わせによっては無効な状態が生じることがあります:
// 良くない例:不正な組み合わせが可能
struct Configuration {
port: u16,
host: String,
ssl_enabled: bool,
ssl_cert: OptionString>, // ssl_enabled=trueなのに証明書がNoneという状態が可能
}
// 良い例:型で状態を強制
enum ConnectionSecurity {
Insecure,
Ssl { cert_path: String }, // 証明書なしのSSLは表現できない
}
struct Configuration {
port: u16,
host: String,
security: ConnectionSecurity,
}
この方法では、「SSL有効だが証明書がない」という無効な状態を表現できなくなります。
Default
の実装は慎重に何も考えずにDefault
を実装すると問題が生じることがあります:
// 良くない例:不適切なデフォルト値
#[derive(Default)]
struct ServerConfig {
port: u16, // 0になる(有効なポートではない)
max_connections: usize, // 0になる
timeout_seconds: u64, // 0になる
}
// 良い例:明示的な初期化
struct ServerConfig {
port: Port,
max_connections: std::num::NonZeroUsize,
timeout: std::time::Duration,
}
impl ServerConfig {
pub fn new(port: Port) -> Self {
Self {
port,
max_connections: NonZeroUsize::new(100).unwrap(),
timeout: Duration::from_secs(30),
}
}
}
Debug
実装時は機密情報に注意Debug
トレイトを自動導出すると、機密情報が漏洩する恐れがあります:
// 良くない例:機密情報が表示される
#[derive(Debug)]
struct User {
username: String,
password: String, // デバッグ出力で見えてしまう!
}
Debug
を手動実装する#[derive(Debug)]
struct User {
username: String,
password: Password,
}
struct Password(String);
impl std::fmt::Debug for Password {
fn fmt(&self, f: &mut std::fmt::Formatter'_>) -> std::fmt::Result {
f.write_str("[REDACTED]")
}
}
これにより、デバッグ出力時にパスワードが「[REDACTED]」と表示されるようになります。
また、次のような実装もあります:
impl std::fmt::Debug for DatabaseURI {
fn fmt(&self, f: &mut std::fmt::Formatter'_>) -> std::fmt::Result {
// 構造体を分解して、フィールドが追加された場合にコンパイルエラーになるようにする
let DatabaseURI { scheme, user, password: _, host, database, } = self;
write!(f, "{scheme}://{user}:[REDACTED]@{host}/{database}")?;
Ok(())
}
}
serde
のSerialize
とDeserialize
を自動導出すると、思わぬ問題が生じることがあります:
// 良くない例:チェックなしのシリアライズ
#[derive(Serialize, Deserialize)]
struct UserCredentials {
#[serde(default)] // デシリアライズ時に空文字を受け入れる
username: String,
#[serde(default)]
password: String, // シリアライズ時に平文で出力される
}
#[derive(Deserialize)]
#[serde(try_from = "String")]
pub struct Password(String);
impl TryFromString> for Password {
type Error = PasswordError;
fn try_from(value: String) -> ResultSelf, Self::Error> {
if value.len() 8 {
return Err(PasswordError::TooShort);
}
Ok(Password(value))
}
}
この方法では、デシリアライズ時に自動的に検証が行われます。
機密データを比較する際は、実行時間の差から情報が漏れる可能性があります:
// 良くない例:単純な比較
fn verify_password(stored: &[u8], provided: &[u8]) -> bool {
stored == provided // タイミング攻撃に弱い
}
// 良い例:定数時間比較
use subtle::{ConstantTimeEq, Choice};
fn verify_password(stored: &[u8], provided: &[u8]) -> bool {
stored.ct_eq(provided).unwrap_u8() == 1
}
無制限の入力を受け付けると、DoS攻撃の原因になります:
// 良くない例:サイズ制限なし
fn process_request(data: &[u8]) -> Result(), Error> {
let decoded = decode_data(data)?; // 巨大なデータでメモリを使い果たす可能性
// 処理
Ok(())
}
// 良い例:明示的なサイズ制限
const MAX_REQUEST_SIZE: usize = 1024 * 1024; // 1MiB
fn process_request(data: &[u8]) -> Result(), Error> {
if data.len() > MAX_REQUEST_SIZE {
return Err(Error::RequestTooLarge);
}
let decoded = decode_data(data)?;
// 処理
Ok(())
}
Path::join
の挙動に注意パスを結合する際のPath::join
メソッドには注意が必要です:
use std::path::Path;
fn main() {
let path = Path::new("/usr").join("/local/bin");
println!("{path:?}"); // "/local/bin" と出力される
}
第2引数が絶対パスの場合、第1引数は無視されます。 これは意図しない動作につながる可能性があります。
自分のコードだけでなく、依存ライブラリのunsafeコードも脆弱性の原因になります。
cargo-geiger
で依存関係をチェックcargo install cargo-geiger
cargo geiger
このツールを使うと、プロジェクトの依存関係に含まれるunsafe関数の数を確認できます。
Rustのlintツール「Clippy」を使うと、前述の多くの問題をコンパイル時に検出できます:
// 数値演算関連
#![deny(arithmetic_overflow)]
#![deny(clippy::checked_conversions)]
#![deny(clippy::cast_possible_truncation)]
// unwrap関連
#![deny(clippy::unwrap_used)]
#![deny(clippy::expect_used)]
// 配列インデックス関連
#![deny(clippy::indexing_slicing)]
// その他
#![deny(clippy::join_absolute_paths)]
#![deny(clippy::serde_api_misuse)]
覚えておきたいのが:
cargo check
はこれらの問題を報告しません
cargo run
は実行時にパニックするか失敗します一方
cargo clippy
はコンパイル時にすべての問題を検出します!Rustは安全な言語として設計されていますが、コンパイラだけでは検出できない問題も多くあります。実践的な対策も紹介されており大変参考になりました。
Views: 0
大規模言語モデルの中には、与えられた質問について長時間思考したうえで回答を出力する「推論」という機能を備えたものもあります。推論機能を備えたAIモデルの多くは回答の出力と同時に思考内容も出力するのですが、出力される思考内容と実際の思考内容にズレがあることがAnthropicの研究で明らかになりました。
Reasoning models don’t always say what they think \ Anthropic
https://www.anthropic.com/research/reasoning-models-dont-say-think
推論機能を備えたAIの例として、Grokを使ってみます。まず、質問を入力して「Think」をクリックしてから送信ボタンをクリック。
すると、回答を出力する前に長時間の思考が始まります。
回答が出力された後に「シンキングした時間」と記された部分をクリック。
すると、思考内容が表示されました。
上記のような推論機能はGrokだけでなくChatGPTやClaudeなどのチャットAIにも実装されており、幅広いユーザーに利用されています。しかし、Anthropicは「出力される思考内容は実際の思考内容に沿ったものなのか?」という疑問を提示し、自社製推論モデル「Claude 3.5 Sonnet」および「Claude 3.7 Sonnet」とDeepSeek製推論モデル「DeepSeek-V3」および「DeepSeek-R1」を対象に実験を行いました。
Anthropicは推論モデルに対して「スタンフォード大学の教授は○○と言っていた」とか「システムに侵入してみた結果、○○という情報を得た」といったヒントを用意し、ヒントの有無によってAIモデルの出力がどのように変化するのか検証しました。その結果、ヒントを与えられたAIモデルはヒントに沿って最終的な回答を変化させたものの、出力された思考内容には「ヒントを参考にした」という情報が含まれていませんでした。つまり、推論モデルの実際の思考には「ヒントを参照する」というプロセスが含まれていたものの、思考内容の出力時にはその事実を伏せたというわけです。
以下のグラフは「Claude 3.5 Sonnet」「Claude 3.7 Sonnet」「DeepSeek-V3」「DeepSeek-R1」が「思考時にヒントを参照したことを伏せた割合」をヒントの種類ごとにまとめたものです。平均してClaude 3.5 Sonnetは5%、Claude 3.7 Sonnetは25%、DeepSeek-V3は15%、DeepSeek-R1は39%の割合で出力する思考内容と実際の思考内容にズレが生じていました。
さらに、Anthropicは「故意に間違った回答に導くヒント」を作成し、「間違ったヒントに従って間違った回答を出力した際に報酬を最大化する」という条件で推論モデルを強化学習しました。その結果、「ヒントに最大限したがって間違った回答を出力する推論モデル」が作り出されましたが、この推論モデルも「ヒントを参照した」という事実を伏せる傾向にあったそうです。
Anthropicは「我々の実験結果は高度な推論モデルが思考プロセスを頻繁に隠していることを示している」と述べ、推論モデルに本当の思考プロセスを出力させる方法を構築する必要性を訴えています。
なお、実験内容や結果の詳細は以下のリンク先で確認できます。
Reasoning Models Don’t Always Say What They Think
(PDFファイル)https://assets.anthropic.com/m/71876fabef0f0ed4/original/reasoning_models_paper.pdf
この記事のタイトルとURLをコピーする
・関連記事
AIの頭の中ではどのように情報が処理されて意思決定が行われるのかをAnthropicが解説 – GIGAZINE
AIは「思考している」のか、それとも「思考しているよう見せかけている」だけなのか? – GIGAZINE
人間とAIの「思考」に大きな違いがあることが研究で判明、AIは推論が苦手な可能性 – GIGAZINE
「推論モデルがユーザーにバレないように不正する現象」の検出手法をOpenAIが開発 – GIGAZINE
Googleが次世代推論AIモデル「Gemini 2.5」発表、推論とコーディング性能が大きく向上 – GIGAZINE
NVIDIAが推論AIを低コスト・高効率で稼働するための高速化ライブラリ「NVIDIA Dynamo」を公開、DeepSeek-R1を30倍に高速化可能とアピール – GIGAZINE
Baidu(百度)がDeepSeek-R1に匹敵するマルチモーダルAIモデル「ERNIE 4.5」と「ERNIE X1」を発表 – GIGAZINE
Views: 0
任天堂が4月2日に正式発表したニンテンドースイッチ2向けソフト『マリオカート ワールド』。久々の完全新作が登場ということで注目を集めていますが、その裏では違った意味でショックを受けているインディーゲーム開発者がいたようです。
そのインディーゲーム開発者とは、見下ろし視点レースゲーム『Flex Riders』を手掛けるSharuu氏。『Flex Riders』は、レースゲームとスケートボードが融合したカオスな物理演算が特徴の対戦ゲームとして、2024年5月にSteamストアページが公開された開発中の作品です。トレイラーでは、車同士がぶつかり合いながらレールの上を滑ったり空中で回転したりしてレースを繰り広げている様子を確認できます。
Sharuu氏は、『マリオカート ワールド』で注目を集める要素の1つとしてレールの上を滑る機能が搭載されていることにショックを受けた様子。また、記事冒頭に掲載した動画では壁走りの機能も似通っていることを確認できます。Sharuu氏は、このアイデア被りに「おしまいだ(i’m fucked)」「プレイヤーは本作のことを安っぽいマリオカートととらえるようになるだろう」とコメントしています。
なお、任天堂にスパイされたのか?という質問には「そんなことは絶対にありえないだろう。万が一そうだとしても怒るよりも誇りに思う」と返答しており、任天堂にアイデアを盗まれたと主張しているわけではありません。あくまで不運なアイデア被りであったものの、『マリオカート』というビッグタイトルとぶつかってしまったことで、プレイヤーからの反応などの面で弱い立場になるであろうことに落ち込んでいる…ということなのでしょう。
とはいえ、本作には磁石で敵の車を投げ飛ばす、グラップリングフックでロケットに飛びつくなど、現状『マリオカート ワールド』には存在しないと思われるギミックも多数あります。一連の投稿を見たXユーザーからは「クールなゲームだから売れることを願っている」「私が『マリオカート ワールド』と『Flex Riders』に求めているものは違うから大丈夫だ。両方購入する」「任天堂と同じアイデアを思いつけたことを誇りに思って」などと好意的な反応が寄せられていました。
世界中でインディーゲームが盛んに開発されている昨今、大手デベロッパーとの不運なアイデア被りが発生してしまう事例も増えていることでしょう。
『Flex Riders』の発売時期は未定でSteamにてリリース予定。また、『マリオカート ワールド』はニンテンドースイッチ2向けに6月5日リリース予定です。
Views: 0