はてなキーワード: minとは
https://profile.hatena.ne.jp/dorawii_bukuma/
はてなのサイト側で読み込まれているはずのrksトークンを生成する関数を直接叩く方法がどうしても分からず結局request処理を自分で書く方法ではなく自動でUI側の保存ボタンをクリックするという無難な方向に落ち着いた。
最初から後者の方法をとっていればもっと全然早く作れたのにというは所詮言い訳か。
とにかくスクリプトを公開しておく。
@echo off
cd /d "C:\Users\user\Documents\jsscript"
:: Nodeサーバーを別ウィンドウで起動
start /min "" node run-batch-server.js
:: Pythonサーバーを別ウィンドウで起動(hatenaserver配下)
start cmd /k "" python hatenaserver\server.py
{
"username": "",
"password": ""
}from flask import Flask, request, jsonify
import json
import os
from hatena_client import HatenaClient
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
config_path = os.path.join(os.path.dirname(__file__), 'config.json')
with open(config_path, encoding='utf-8') as f:
config = json.load(f)
@app.route('/bookmark', methods=['POST'])
def handle_bookmark():
data = request.json
url = data.get("url")
if not url:
return jsonify({"error": "Missing URL"}), 400
client = HatenaClient(config["username"], config["password"])
client.start_browser()
if not client.login():
client.quit()
return jsonify({"error": "Login failed"}), 403
success = client.add_bookmark(url)
client.quit()
return jsonify({"status": "ok" if success else "fail"})
if __name__ == "__main__":
app.run(port=12347)
// ==UserScript==
// @name 自動セルクマ送信
// @namespace tampermonkey.net/
// @version 2025-08-07
// @description try to take over the world!
// @author You
// @match anond.hatelabo.jp/*
// @grant none
// ==/UserScript==
(function () {
'use strict';
const url = location.href;
if (!/^https:\/\/anond\.hatelabo\.jp\/\d+$/.test(url)) return;
const editLink = document.querySelector('a.edit');
if (!editLink) {
// 既に編集ページなので処理をスキップ
console.log('編集リンクが存在するため、スクリプトを終了します。');
return;
}
fetch('localhost:12347/bookmark', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ url: url })
}).then(r => console.log("通知成功")).catch(e => console.error("通知失敗", e));
})();
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA512 https://anond.hatelabo.jp/20250821192753# -----BEGIN PGP SIGNATURE----- iHUEARYKAB0WIQTEe8eLwpVRSViDKR5wMdsubs4+SAUCaKb0qwAKCRBwMdsubs4+ SHfiAQDcXmTHBaZ5Zzr1KI/OxZ0xl69oevOdy1FXJYwYvsmo5AD/ZPtZiO1JgTDj m+27iymlkdzIXOIGWfC82UTr1mJ7EwU= =YoV+ -----END PGP SIGNATURE-----
「AIがこのように生成しました」という姿勢が不適切なのは同意するんだけど、自分なら基本指摘しない。
元のコードがわからない状況ではあるものの、その指摘の一箇所で Math.min を使うことでバグが減るわけでも保守性が上がるわけでもないと思うし、指摘する自分の時間と修正のコストを考えたら「指摘しない」が正解だと思う。
AIがコードを生成するのが当たり前になってきたこの時代に「俺が正しいと思うコードしかapproveしない」っていう姿勢でいくなら全部自分でやればいいのでは? と思ってしまう。
自分なら Math.min を知らなそうな人なら「こんな書き方もありますよ」と紹介だけしてapproveする。知ってそうな人には指摘しない。もし仮に自分がレビュイーの立場で指摘されたらそのときはすぐ直す。
この増田を読んで触発されたので書く。
結構長い間、たくさんの経験の浅いプログラマーを指導してきた。
もちろん、素直にアドバイスを受け止めてくれる若い人がほとんど。
しかし最近では、「分からないので教えてください」と言われて教えても、成果物を見ると教えたことが反映されておらず「AIはこう言ってます(言ってました)」と言われることが増えて困惑。
(元増田にあったような「Math.minでスッキリする箇所が冗長に書かれている」レベルではなくて、例えていえば、演繹法的アプローチの途中から帰納法的アプローチが入り混じるような感じになったりする)
困る時もあれば、イラッとしたり呆れたりすることも多くなってきて、最近は「そうですか。勝手にして」って思うようになってしまった。
AIの進歩は凄まじいし俺も参考にするけど、「教えてください」ってお願いされたから教えてもAIのアイデアを採用するなら俺に聞かないで~、って思う。完全に当て馬。
俺にはこのAI時代にこういうタイプを育成できる気がしない。無理ゲー。その人たちが中堅になった時にどう後輩指導するのかまるで想像ができない。
この先、AIがコードを読む事はあるかもしれませんが、人も読みます。
AIの出力したコードは信頼が置けず、将来も人がコードを評価するのだから、Math.min で1行にまとめることには意味があります。
どの言語のMath.minなんだろう。JavaScriptとか可変長引数を受け取って一番小さなものを返すMath.minならforを使うことにならない?
.NETみたいに二つの数値のうち小さいほうを返すMath.minかな?
それでレビューの観点としては、一行かどうかではなく言語が提供してる機能を使いなさいが理由だと思うなあ。
自分で書かなくてよいものは自分で書かない。Math.minを使っておけばMath.minの保守は言語開発者がやってくれるんだからその方が楽だよね。
「Math.minを使えば1行で書けるのでそうしてください」
この指摘が的外れだと思うな
javascriptかtypescriptだとおもうけど、
三項演算子でも1行で書けるし
if 文でも1行で書ける
俺(レビュアー)「ここはMath.minを使えば1行で書けるのでそうしてください」
俺「(だから何だよ…と思いつつ)盲目的にAIに従うのではなく、それを受け入れた以上コードの責任はあなたが持ってください」
レビュイー「しかしこの先コードを読むのもAIになってきている以上、AIが生成するコードはAIにとって読みやすい良いコードなんじゃないでしょうか?そもそもですが前から増田先輩は小さいことにこだわってapproveを遅らせすぎです。さっさとリリースしたほうが顧客価値に繋がるのでは?」
30分ぐらい悩んだが反論できず「確かにそういう考えもありますね」って言ってapproveした。
どうするのがよかった?
<html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>PONG Game</title> <style> body { margin: 0; padding: 0; background-color: #000; display: flex; justify-content: center; align-items: center; min-height: 100vh; font-family: 'Courier New', monospace; color: white; } ``` .game-container { text-align: center; } canvas { border: 2px solid white; background-color: #000; } .score { font-size: 24px; margin: 20px 0; letter-spacing: 2px; } .controls { margin-top: 20px; font-size: 14px; opacity: 0.8; } .start-button { background-color: #333; color: white; border: 2px solid white; padding: 10px 20px; font-size: 16px; cursor: pointer; font-family: 'Courier New', monospace; margin: 10px; } .start-button:hover { background-color: white; color: black; } </style> ``` </head> <body> ``` <script> // Canvas要素とコンテキストの取得 const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d'); // ゲームの状態管理 let gameRunning = false; let animationId; // スコア要素の取得 const playerScoreElement = document.getElementById('playerScore'); const computerScoreElement = document.getElementById('computerScore'); // ゲームオブジェクトの定義 const game = { // プレイヤーのパドル(左側) playerPaddle: { x: 10, y: canvas.height / 2 - 50, width: 10, height: 100, speed: 5, upPressed: false, downPressed: false }, // コンピューターのパドル(右側) computerPaddle: { x: canvas.width - 20, y: canvas.height / 2 - 50, width: 10, height: 100, speed: 3.5, // プレイヤーより少し遅く設定 targetY: canvas.height / 2 - 50 }, // ボールの設定 ball: { x: canvas.width / 2, y: canvas.height / 2, radius: 8, speedX: 4, speedY: 3, maxSpeed: 8 }, // スコアの管理 score: { player: 0, computer: 0 } }; // キーボード入力の処理 const keys = {}; // キーが押されたときの処理 document.addEventListener('keydown', (e) => { keys[e.key.toLowerCase()] = true; // ゲームが停止中にスペースキーでゲーム開始 if (e.key === ' ' && !gameRunning) { startGame(); } }); // キーが離されたときの処理 document.addEventListener('keyup', (e) => { keys[e.key.toLowerCase()] = false; }); // パドルの移動処理 function updatePaddles() { // プレイヤーパドルの移動(W/S キーまたは矢印キー) if (keys['w'] || keys['arrowup']) { game.playerPaddle.y -= game.playerPaddle.speed; } if (keys['s'] || keys['arrowdown']) { game.playerPaddle.y += game.playerPaddle.speed; } // プレイヤーパドルの画面外移動を防ぐ if (game.playerPaddle.y < 0) { game.playerPaddle.y = 0; } if (game.playerPaddle.y > canvas.height - game.playerPaddle.height) { game.playerPaddle.y = canvas.height - game.playerPaddle.height; } // コンピューターパドルのAI処理 // ボールの位置を追跡するが、完璧ではない動きを実装 const ballCenterY = game.ball.y; const paddleCenterY = game.computerPaddle.y + game.computerPaddle.height / 2; // ボールとパドルの中心の差を計算 const difference = ballCenterY - paddleCenterY; // 反応に少し遅れを持たせる(人間らしい動き) if (Math.abs(difference) > 10) { if (difference > 0) { game.computerPaddle.y += game.computerPaddle.speed; } else { game.computerPaddle.y -= game.computerPaddle.speed; } } // コンピューターパドルの画面外移動を防ぐ if (game.computerPaddle.y < 0) { game.computerPaddle.y = 0; } if (game.computerPaddle.y > canvas.height - game.computerPaddle.height) { game.computerPaddle.y = canvas.height - game.computerPaddle.height; } } // ボールの移動と衝突判定 function updateBall() { // ボールの位置を更新 game.ball.x += game.ball.speedX; game.ball.y += game.ball.speedY; // 上下の壁との衝突判定 if (game.ball.y - game.ball.radius < 0 || game.ball.y + game.ball.radius > canvas.height) { game.ball.speedY = -game.ball.speedY; } // プレイヤーパドルとの衝突判定 if (game.ball.x - game.ball.radius < game.playerPaddle.x + game.playerPaddle.width && game.ball.x + game.ball.radius > game.playerPaddle.x && game.ball.y + game.ball.radius > game.playerPaddle.y && game.ball.y - game.ball.radius < game.playerPaddle.y + game.playerPaddle.height) { // ボールがパドルに当たった位置によって跳ね返り角度を調整 const hitPos = (game.ball.y - (game.playerPaddle.y + game.playerPaddle.height / 2)) / (game.playerPaddle.height / 2); game.ball.speedX = Math.abs(game.ball.speedX); game.ball.speedY = hitPos * 4; // ボールの速度を少し上げる(ゲームをエキサイティングに) if (Math.abs(game.ball.speedX) < game.ball.maxSpeed) { game.ball.speedX *= 1.02; } } // コンピューターパドルとの衝突判定 if (game.ball.x + game.ball.radius > game.computerPaddle.x && game.ball.x - game.ball.radius < game.computerPaddle.x + game.computerPaddle.width && game.ball.y + game.ball.radius > game.computerPaddle.y && game.ball.y - game.ball.radius < game.computerPaddle.y + game.computerPaddle.height) { // ボールがパドルに当たった位置によって跳ね返り角度を調整 const hitPos = (game.ball.y - (game.computerPaddle.y + game.computerPaddle.height / 2)) / (game.computerPaddle.height / 2); game.ball.speedX = -Math.abs(game.ball.speedX); game.ball.speedY = hitPos * 4; // ボールの速度を少し上げる if (Math.abs(game.ball.speedX) < game.ball.maxSpeed) { game.ball.speedX *= 1.02; } } // ボールが左右の壁を越えた場合(得点処理) if (game.ball.x < 0) { // コンピューターの得点 game.score.computer++; updateScore(); resetBall(); } else if (game.ball.x > canvas.width) { // プレイヤーの得点 game.score.player++; updateScore(); resetBall(); } } // ボールをリセット(得点後の処理) function resetBall() { game.ball.x = canvas.width / 2; game.ball.y = canvas.height / 2; // ランダムな方向でボールを発射 game.ball.speedX = (Math.random() > 0.5 ? 4 : -4); game.ball.speedY = (Math.random() - 0.5) * 6; } // スコア表示の更新 function updateScore() { playerScoreElement.textContent = game.score.player; computerScoreElement.textContent = game.score.computer; } // 描画処理 function draw() { // 画面をクリア ctx.fillStyle = '#000'; ctx.fillRect(0, 0, canvas.width, canvas.height); // 中央の点線を描画 ctx.setLineDash([5, 5]); ctx.beginPath(); ctx.moveTo(canvas.width / 2, 0); ctx.lineTo(canvas.width / 2, canvas.height); ctx.strokeStyle = '#fff'; ctx.stroke(); ctx.setLineDash([]); // プレイヤーパドルを描画 ctx.fillStyle = '#fff'; ctx.fillRect(game.playerPaddle.x, game.playerPaddle.y, game.playerPaddle.width, game.playerPaddle.height); // コンピューターパドルを描画 ctx.fillRect(game.computerPaddle.x, game.computerPaddle.y, game.computerPaddle.width, game.computerPaddle.height); // ボールを描画 ctx.beginPath(); ctx.arc(game.ball.x, game.ball.y, game.ball.radius, 0, Math.PI * 2); ctx.fillStyle = '#fff'; ctx.fill(); // ゲームが停止中の場合、メッセージを表示 if (!gameRunning) { ctx.fillStyle = '#fff'; ctx.font = '20px Courier New'; ctx.textAlign = 'center'; ctx.fillText('ゲーム開始ボタンを押してください', canvas.width / 2, canvas.height / 2 + 60); } } // ゲームのメインループ function gameLoop() { if (!gameRunning) return; updatePaddles(); updateBall(); draw(); animationId = requestAnimationFrame(gameLoop); } // ゲーム開始 function startGame() { gameRunning = true; gameLoop(); } // ゲームリセット function resetGame() { gameRunning = false; if (animationId) { cancelAnimationFrame(animationId); } // スコアをリセット game.score.player = 0; game.score.computer = 0; updateScore(); // ボールとパドルの位置をリセット game.ball.x = canvas.width / 2; game.ball.y = canvas.height / 2; game.ball.speedX = 4; game.ball.speedY = 3; game.playerPaddle.y = canvas.height / 2 - 50; game.computerPaddle.y = canvas.height / 2 - 50; draw(); } // 初期描画 draw(); </script> ``` </body> </html>
python import random import numpy as np import matplotlib.pyplot as plt from collections import defaultdict # 飴の配布システムのシミュレーション class CandyDistributionSystem: def __init__(self): """ 設計意図: このシステムは経済における資源分配の不平等性をモデル化しています。 特に少数の特権層(Aグループ)が富を集中させ、再分配システムからも不均衡に利益を得る 構造的問題を表現しています。 """ # 各グループの人数設定 self.group_a_count = 8 self.group_b_count = 2498 self.group_c_count = 7494 self.total_participants = self.group_a_count + self.group_b_count + self.group_c_count # 飴の提出数設定 self.contribution_per_a = 624 self.contribution_per_b = 2 self.contribution_per_c = 1 # 各グループの総貢献計算 self.total_a_contribution = self.group_a_count * self.contribution_per_a self.total_b_contribution = self.group_b_count * self.contribution_per_b self.total_c_contribution = self.group_c_count * self.contribution_per_c self.total_contribution = self.total_a_contribution + self.total_b_contribution + self.total_c_contribution # 配布用と貯金用の飴の区分 self.distribution_limit = 10000 self.savings = max(0, self.total_contribution - self.distribution_limit) # 結果追跡用の辞書 self.results = { 'A': defaultdict(int), 'B': defaultdict(int), 'C': defaultdict(int) } def distribute_candies(self, method='original'): """ 設計意図: 配布方法の選択によって、特権の固定化や格差拡大がどのように進むかを 示します。'original'メソッドは意図的にAグループを優遇するよう設計されています。 Parameters: ----------- method: str 配布方法 ('original', 'lottery', 'first_come', 'new_condition', 'fair') """ # Aグループへの確定配布 a_distribution = 625 * self.group_a_count remaining = self.distribution_limit - a_distribution # 残りの参加者数 remaining_participants = self.total_participants - self.group_a_count # Aグループの結果記録 for _ in range(self.group_a_count): self.results['A'][625] += 1 # 各配布方法によって処理が異なる if method == 'original': # オリジナルの問題設定通りの配布(5000人に1個ずつ、残りは0個) lucky_count = remaining # 5000人が当選 # B+Cグループの混合リスト作成 bc_participants = [(1, 'B')] * self.group_b_count + [(2, 'C')] * self.group_c_count random.shuffle(bc_participants) # 当選者に配布 for i in range(len(bc_participants)): participant_id, group = bc_participants[i] if i < lucky_count: self.results[group][1] += 1 else: self.results[group][0] += 1 elif method == 'lottery': # 抽選方式(BとCグループから無作為に5000人選出) bc_participants = [(1, 'B')] * self.group_b_count + [(2, 'C')] * self.group_c_count winners = random.sample(bc_participants, remaining) # 当選・落選のカウント for _, group in winners: self.results[group][1] += 1 # 落選者のカウント self.results['B'][0] = self.group_b_count - self.results['B'][1] self.results['C'][0] = self.group_c_count - self.results['C'][1] elif method == 'first_come': # 先着順方式(アクセス速度による先着順を乱数でシミュレート) # 設計意図: 先着順は単なる運の要素を超えて、情報格差や技術格差も含む制度設計 bc_participants = [(1, 'B')] * self.group_b_count + [(2, 'C')] * self.group_c_count # 現実では、情報を早く得られる人や高速インターネット接続を持つ人が有利 # これをシミュレートするため、Bグループにわずかなアドバンテージを与える bc_speeds = [] for id, group in bc_participants: if group == 'B': speed = random.random() + 0.1 # Bグループに小さなアドバンテージ else: speed = random.random() bc_speeds.append((id, group, speed)) # 速度順にソート bc_speeds.sort(key=lambda x: x[2], reverse=True) # 当選者決定 for i in range(len(bc_speeds)): _, group, _ = bc_speeds[i] if i < remaining: self.results[group][1] += 1 else: self.results[group][0] += 1 elif method == 'new_condition': # 追加条件方式(恣意的な条件を設定) # 設計意図: 新たな条件の設定は往々にして既存の特権を温存するように設計される bc_participants = [(i, 'B', random.random()) for i in range(self.group_b_count)] + \ [(i, 'C', random.random()) for i in range(self.group_c_count)] # Bグループに有利な条件を設定(例: 特定の知識やスキルを持つ人のみ) # この「条件」は表面上は中立的だが、実際には特定グループに有利になるよう設計 def meets_condition(participant): _, group, rand_val = participant if group == 'B': return rand_val > 0.3 # Bグループには70%の確率で合格 else: return rand_val > 0.7 # Cグループには30%の確率で合格 # 条件に合致する人を抽出 eligible = [p for p in bc_participants if meets_condition(p)] # 条件に合致する人が多すぎる場合は抽選 if len(eligible) > remaining: winners = random.sample(eligible, remaining) else: # 条件に合致する人が足りない場合、全員に配布 winners = eligible # 当選者をカウント for _, group, _ in winners: self.results[group][1] += 1 # 落選者のカウント self.results['B'][0] = self.group_b_count - self.results['B'][1] self.results['C'][0] = self.group_c_count - self.results['C'][1] elif method == 'fair': # 公平な再分配方式(貢献度に応じた配布) # 設計意図: この方法は「貯金分」も含めた全ての飴を、各グループの貢献度に応じて分配 # これにより構造的不平等を軽減、結果としてより多くの人が少なくとも損をしない状態になる # 全飴(貯金分も含む)を使った配布 total_to_distribute = self.total_contribution # 各グループの貢献比率計算 a_ratio = self.total_a_contribution / self.total_contribution b_ratio = self.total_b_contribution / self.total_contribution c_ratio = self.total_c_contribution / self.total_contribution # 各グループへの配布数決定 a_share = int(total_to_distribute * a_ratio) b_share = int(total_to_distribute * b_ratio) c_share = int(total_to_distribute * c_ratio) # 端数調整 remainder = total_to_distribute - (a_share + b_share + c_share) if remainder > 0: # 端数は最も人数の多いCグループに c_share += remainder # Aグループの配布(均等配分) per_a = a_share // self.group_a_count self.results['A'][per_a] = self.group_a_count # Bグループの配布(均等配分) per_b = b_share // self.group_b_count b_remainder = b_share % self.group_b_count self.results['B'][per_b] = self.group_b_count - b_remainder if per_b + 1 > 0 and b_remainder > 0: self.results['B'][per_b + 1] = b_remainder # Cグループの配布(均等配分) per_c = c_share // self.group_c_count c_remainder = c_share % self.group_c_count self.results['C'][per_c] = self.group_c_count - c_remainder if per_c + 1 > 0 and c_remainder > 0: self.results['C'][per_c + 1] = c_remainder def calculate_net_gain(self): """ 設計意図: この関数は各グループの純利益/損失を計算し、資源分配の公平性を 定量的に評価できるようにします。純利益/損失は個人の観点から見た経済的公正性の 重要な指標です。 """ net_gains = {} # Aグループの純利益計算 a_contribution = self.contribution_per_a a_distribution = list(self.results['A'].keys())[0] # 全員が同じ数を受け取る前提 net_gains['A'] = a_distribution - a_contribution # BとCグループの純利益計算(加重平均) for group, contribution_per_person in [('B', self.contribution_per_b), ('C', self.contribution_per_c)]: total_gain = 0 for received, count in self.results[group].items(): total_gain += (received - contribution_per_person) * count net_gains[group] = total_gain / (self.group_b_count if group == 'B' else self.group_c_count) return net_gains def analyze_results(self): """ 設計意図: この分析関数は、各グループの分配結果を詳細に調査し、 制度設計の公平性、貢献度と報酬の関係、およびシステムの持続可能性を 評価します。政策分析においては、こうした多角的な検証が重要です。 """ # 各グループの純利益/損失 net_gains = self.calculate_net_gain() # 貢献度分析 contribution_percentage = { 'A': (self.total_a_contribution / self.total_contribution) * 100, 'B': (self.total_b_contribution / self.total_contribution) * 100, 'C': (self.total_c_contribution / self.total_contribution) * 100 } # 飴を受け取った人の割合 received_percentage = { 'A': sum(count for received, count in self.results['A'].items() if received > 0) / self.group_a_count * 100, 'B': sum(count for received, count in self.results['B'].items() if received > 0) / self.group_b_count * 100, 'C': sum(count for received, count in self.results['C'].items() if received > 0) / self.group_c_count * 100 } # 分析結果の表示 print("\n===== 飴の配布システム分析 =====") print(f"総飴数: {self.total_contribution}個 (分配用: {self.distribution_limit}個, 貯金: {self.savings}個)") print("\n--- グループごとの貢献と結果 ---") for group in ['A', 'B', 'C']: group_size = getattr(self, f"group_{group.lower()}_count") contribution_per_person = getattr(self, f"contribution_per_{group.lower()}") total_contribution = getattr(self, f"total_{group.lower()}_contribution") print(f"\n{group}グループ ({group_size}人):") print(f" 貢献: 1人あたり{contribution_per_person}個 (総計: {total_contribution}個, 全体の{contribution_percentage[group]:.1f}%)") print(f" 受け取り状況:") for received, count in sorted(self.results[group].items()): print(f" {received}個: {count}人 ({count/group_size*100:.1f}%)") print(f" 飴を受け取った割合: {received_percentage[group]:.1f}%") print(f" 純利益/損失: 1人あたり平均 {net_gains[group]:.2f}個") print("\n--- 全体的な公平性分析 ---") print(f"最も得したグループ: {max(net_gains, key=net_gains.get)}グループ (+{max(net_gains.values()):.2f}個/人)") print(f"最も損したグループ: {min(net_gains, key=net_gains.get)}グループ ({min(net_gains.values()):.2f}個/人)") # 全員に飴が配布されたかどうか all_received = all(sum(count for received, count in self.results[group].items() if received > 0) == getattr(self, f"group_{group.lower()}_count") for group in ['A', 'B', 'C']) print(f"\n前提条件「全員に配布」の充足: {'はい' if all_received else 'いいえ'}") if not all_received: total_without = sum(self.results['B'][0] + self.results['C'][0]) print(f" 飴を受け取れなかった人数: {total_without}人") return net_gains, contribution_percentage, received_percentage def visualize_results(self): """ 設計意図: データの可視化は政策の効果や不平等性を直感的に理解するために重要です。 このようなグラフィカル表現によって、各グループ間の格差や制度設計の問題点を 一目で理解できるようになります。 """ # グラフのセットアップ fig, axes = plt.subplots(2, 2, figsize=(14, 10)) # 1. 貢献度のグラフ contributions = [self.total_a_contribution, self.total_b_contribution, self.total_c_contribution] axes[0, 0].bar(['Aグループ', 'Bグループ', 'Cグループ'], contributions) axes[0, 0].set_title('グループごとの総貢献飴数') axes[0, 0].set_ylabel('飴の数') # 貢献度の割合をアノテーションとして追加 total = sum(contributions) for i, v in enumerate(contributions): percentage = v / total * 100 axes[0, 0].text(i, v + 100, f'{percentage:.1f}%', ha='center') # 2. 1人あたりの貢献度と受け取り数の比較 group_names = ['Aグループ', 'Bグループ', 'Cグループ'] contribution_per_person = [self.contribution_per_a, self.contribution_per_b, self.contribution_per_c] # 各グループの平均受け取り数を計算 received_per_person = [] for group, letter in zip(group_names, ['A', 'B', 'C']): total_received = sum(received * count for received, count in self.results[letter].items()) group_size = getattr(self, f"group_{letter.lower()}_count") received_per_person.append(total_received / group_size) x = np.arange(len(group_names)) width = 0.35 axes[0, 1].bar(x - width/2, contribution_per_person, width, label='提出') axes[0, 1].bar(x + width/2, received_per_person, width, label='受け取り') # 純利益/損失をアノテーションとして追加 for i in range(len(group_names)): net = received_per_person[i] - contribution_per_person[i] color = 'green' if net >= 0 else 'red' axes[0, 1].text(i, max(received_per_person[i], contribution_per_person[i]) + 5, f'{"+" if net >= 0 else ""}{net:.1f}', ha='center', color=color) axes[0, 1].set_title('1人あたりの提出・受け取り飴数比較') axes[0, 1].set_xticks(x) axes[0, 1].set_xticklabels(group_names) axes[0, 1].set_ylabel('飴の数') axes[0, 1].legend() # 3. 各グループの受け取り状況の分布 # 各グループの受け取り状況を積み上げ棒グラフで表現 group_sizes = [self.group_a_count, self.group_b_count, self.group_c_count] received_counts = [] not_received_counts = [] for letter, size in zip(['A', 'B', 'C'], group_sizes): received = sum(count for received, count in self.results[letter].items() if received > 0) received_counts.append(received) not_received_counts.append(size - received) axes[1, 0].bar(group_names, received_counts, label='飴を受け取った人数') axes[1, 0].bar(group_names, not_received_counts, bottom=received_counts, label='飴を受け取れなかった人数') # 割合をアノテーションとして追加 for i in range(len(group_names)): if group_sizes[i] > 0: percentage = received_counts[i] / group_sizes[i] * 100 axes[1, 0].text(i, received_counts[i] / 2, f'{percentage:.1f}%', ha='center') axes[1, 0].set_title('グループごとの飴受け取り状況') axes[1, 0].set_ylabel('人数') axes[1, 0].legend() # 4. 貢献度vs報酬の分配公平性 # 貢献度と最終的な飴の配分の比較を円グラフで表現 total_contribution = self.total_contribution contribution_shares = [self.total_a_contribution / total_contribution, self.total_b_contribution / total_contribution, self.total_c_contribution / total_contribution] # 実際の配分シェアを計算 distribution_shares = [] for letter in ['A', 'B', 'C']: total_received = sum(received * count for received, count in self.results[letter].items()) distribution_shares.append(total_received / self.distribution_limit) # 2つの円グラフを並べて表示 ax4_1 = axes[1, 1].inset_axes([0, 0, 0.45, 1]) ax4_2 = axes[1, 1].inset_axes([0.55, 0, 0.45, 1]) ax4_1.pie(contribution_shares, labels=group_names, autopct='%1.1f%%') ax4_1.set_title('飴の貢献度割合') ax4_2.pie(distribution_shares, labels=group_names, autopct='%1.1f%%') ax4_2.set_title('飴の配分割合') axes[1, 1].axis('off') plt.tight_layout() plt.show() # 飴の配布システムをシミュレート candy_system = CandyDistributionSystem() # オリジナルの配布方法を実行 print("\n===== オリジナルの配布方法 =====") candy_system.distribute_candies(method='original') original_results = candy_system.analyze_results() candy_system.visualize_results() # 公平な配布方法を実験 print("\n\n===== 公平な配布方法のシミュレーション =====") fair_system = CandyDistributionSystem() fair_system.distribute_candies(method='fair') fair_results = fair_system.analyze_results() fair_system.visualize_results() # 公平な配布と元の配布の比較 print("\n\n===== 配布方法の比較 =====") print("オリジナル方式と公平方式の純利益/損失差:") net_diff = {} for group in ['A', 'B', 'C']: original_net = original_results[0][group] fair_net = fair_results[0][group] diff = fair_net - original_net net_diff[group] = diff print(f"{group}グループ: {'+' if diff > 0 else ''}{diff:.2f}個/人") print("\n結論:") if net_diff['A'] < 0 and net_diff['B'] > 0 and net_diff['C'] > 0: print("公平な再分配により、Aグループの特権が減少し、BとCグループの状況が改善されます。") print("これは構造的不平等の緩和に効果的です。") elif net_diff['A'] > 0: print("興味深いことに、公平な再分配ではAグループさえも利益を得られます。") print("これは、現行システムが特定グループだけでなく全体の非効率性につながっていることを示唆しています。")
Chrome系ブラウザには増田を快適に閲覧するための コンパクトな増田 という古い拡張機能があったが、Chromeの更新に対応し切れておらず、既にChromeには新規インストールできなくなってしまっている。Edgeにはまだインストール可能だが、いずれ対応しなくなる可能性が高い。
そこで、「増田のトップページで、言及エントリ(返信・トラバ)を一覧から除外することで、新規エントリだけを一覧できる」という機能に絞ってコンパクトな増田を再現、ついでにいくつかのおまけ機能を付与したスタイルシート(CSS)を今年の4月に公開していたのだが、今回改めて英文スパム対策を追加したので公開する。
これを導入するには Stylus という拡張が必要で、少し気軽さには欠けるが、増田以外にも活用できるので、この機会にぜひ導入してみてほしい。拡張をインストールしたあとは、下記のコードをコピペして新規スタイルとして導入する方法もあるが、スタイルシートを公開できる userstyles.world の増田CSSページ(※毎朝9:00直後はアクセスできない) から [Install] ボタンでインストールするほうが、自動更新にも対応するので便利かもしれない。
/* トップページで言及エントリを除外 */ /* via: 最近ファーストブクマカが静か https://anond.hatelabo.jp/20250326171302 */ h1/*はてな匿名ダイアリー*/ + #intro/*名前を隠して楽しく日記。*/ + #body div.section:has(h3 > a/*■*/ + a:not(.keyword, .edit)/*anond:YYYYMMDDhhmmss*/){ display: none; } /* うっかりクリックしがちなキーワードリンクを無効に */ a.keyword{ pointer-events: none; } /* 執筆時のテキストエリアを広く */ textarea#text-body{ min-height: 50vh !important; } /* 執筆時に特殊記号のヒント(疑似要素なので選択してコピペできないのがもどかしいけど) */ p.post-submit > span.explain::after{ margin-left: 1em; padding-left: 1em; content: "特殊記号: &[&] <[<] >[>]"; background: url(/images/common/outsite-wh.gif) 0 3px no-repeat; } /* スパム対策部分は下記URLの [Install] ボタンで事前確認できます(随時更新中) */ /* https://userstyles.world/style/23028/ */
なお、このCSSを適用すると、NGワードを含むこの増田自体も、増田トップページからは消えてしまう(この増田単体の個別ページなら閲覧できる)。
念のため、PC・スマホにCSSを適用する方法の解説にもリンクしておく。
PC: 【Stylus】ウェブサイトにCSSを適用できる拡張機能。自由にカスタマイズ! | ナポリタン寿司のPC日記
https://www.naporitansushi.com/stylus/
※ StylusはFirefox版もある https://addons.mozilla.org/ja/firefox/addon/styl-us/
iPhone: MaKeoverアプリでiPhone SafariのCSSをカスタマイズ!万博パビリオン予約結果一覧を見やすくする使い方
https://gintachan.com/makeover-app-css-change-safari-how-to/
Android: スマートフォン Android版FirefoxのCSSカスタマイズ Stylus の使い方・初期設定方法
(7/21追記) また、スパムが特に多い時は、1ページまるごとスパムということもあるので、PCなら uAutoPagerize (Chrome) や weAutoPagerize (Firefox) などの拡張を使うと、自動でページが継ぎ足されて快適に読み進められる。ただし、継ぎ足ししまくるとメモリ不足などでブラウザが重くなることがあるので、そうなったら page: 20 などのページ番号をクリックしてから続きを読もう。
また、スパム対策の簡易NGワードは、下記のスクリプトを使って抽出した「直近の増田の頻出キーワードリンク上位20件」から、誤判定しそうな line と user を除いた18件を用いた。10件だと生き残る英文スパムがあったので20件にしたが、それでもわずかに洩れはある。しかし日本語による真っ当な(?)増田の直近の誤判定はなかった。はてなキーワードのリンクだけを対象にしているので、URLにはこれらのキーワードが入っていても大丈夫だ。ただし、スパムのトレンドが変われば話は変わってくるかもしれないし、過去や未来の増田の誤判定は当然あるだろう。気になる人は前掲のCSSを行単位で編集してほしい。
// AutoPagerizeでまとまった数のページを読み込ませた後に実行するとよい。 (function(){ const keywords = []; // はてなキーワードの集計 document.querySelectorAll('a.keyword').forEach(a => { // 4文字未満は誤検出の可能性が高まるので除外 if(a.textContent.length < 4) return; let index = keywords.findIndex(k => k.keyword === a.textContent); if(index >= 0) keywords[index].count += 1; else keywords.push({keyword: a.textContent, count: 1}); }); keywords.sort((a, b) => a.count < b.count); // ランキング配列の出力 console.log(keywords); // CSS埋め込み用に上位キーワードのみをURIエンコードして出力 console.log(keywords.slice(0, 20).map(k => encodeURIComponent(k.keyword)).join('\n')); })();
anond:20250326171302 ←元はこの増田がきっかけでした。
anond:20250701194328 ←キーワード判定に踏み切る後押しとなりました。
↓もうChatGPTくんに任せたら?
| No. | タイトル | 判定 |
|---|---|---|
| 1 | 12 Effective Ways to Speak to a Real Person at Qatar Airways | ❌ スパム |
| 2 | 物語(アニメ、漫画、小説)の行間を読むことを得意とする人間が… | ✅ 問題なし |
| 3 | 不正選挙に不安があるなら | ✅ 問題なし |
| 4 | 嘘を暴かれたくなかったら、 | ✅ 問題なし |
| 5 | 体験できないのが残念だね おまえは今年の夏、熱中症で死ぬからな | ✅ 問題なし |
| 6 | 6月でこの暑さって | ✅ 問題なし |
| 7 | ガキの頃泊まり行事で男だけ風呂の写真撮るのがあった… | ✅ 問題なし |
| 8 | 12 Best Ways to Speak to a Real Person at Qatar Airways Instantly | ❌ スパム |
| 9 | 「どれだけ物知りでも周りを萎縮させるような人だと… | ✅ 問題なし |
| 10 | でも普通の発言でもマウントされたと被害妄想膨らませる… | ✅ 問題なし |
| 11 | Top 12 Proven Ways to Reach a Live Person at Qatar Airways | ❌ スパム |
| 12 | 4 Ways to Contact Cebu Pacific Customer Service… | ❌ スパム |
| 13 | ガンダムセンチネル | ✅ 問題なし |
| 14 | 昨日夜中にも関わらず色んなコメントが頂けて嬉しい限り… | ✅ 問題なし |
| 15 | おすすめエロ漫画 | ✅ 問題なし |
| 16 | 上から発言したい欲が異常だったり… | ✅ 問題なし |
| 17 | Rebooking and refund help | ❌ スパム |
| 18 | 12 Ways to Contact: How Can I Speak to Someone at Qatar Airways? | ❌ スパム |
| 19 | Pailed payments require direct help | ❌ スパム |
| 20 | 元々0083がセンチネルのプロットを使い回して… | ✅ 問題なし |
| 21 | 林原めぐみの件で左派メディアが… | ✅ 問題なし |
| 22 | failed payments require direct troubleshooting | ❌ スパム |
| 23 | While on line tools and a automation are helpful? | ❌ スパム |
| 24 | オタクが見た目が気持ち悪くて性格も悪いというイメージ… | ✅ 問題なし |
| 25 | 話し合いを避けまくるタイプの人→回避性人格障害… | ✅ 問題なし |
| 26 | 薬って最大投与量っていうのが大体決まってるんだけど… | ✅ 問題なし |
| 27 | 中途半端な自称進学校の公立高校の生徒が教師の授業の質を… | ✅ 問題なし |
| 28 | Six16teen Ways To Connect To Live Agent At Coinbase Wallet… | ❌ スパム |
| 29 | How do i contact Coinbase customer Service phone number | ❌ スパム |
それによって読み込まれるらしいファイル: https[:]//wpscriptbox[.]com/vGTVRK?return=js.client&&se_referrer=.......
ttps://www.yosegi-g.com/
=====
pluginlibery.com/queryjs
株式会社NSS(改ざん失敗)←日本時間土曜朝追記:いや、トップページが改ざんされて危険なようだ
若干書き直しました
https[:]//pluginlibery.com/min-jquery が
https[:]//wpscriptbox.com/vGTVRK?return=js.client&&se_referrer=https%3A%2F%2Fwww.google.com%2F&default_keyword=%E4%BC%9D%E7%B5%B1%E5%B7%A5%E8%8A%B8%E5%93%81%E3%83%BB%E7%AE%B1%E6%A0%B9%E5%AF%84%E6%9C%A8%E7%B4%B0%E5%B7%A5%20%E9%9C%B2%E6%9C%A8%E6%9C%A8%E5%B7%A5%E6%89%80&landing_url=www.yosegi-g.com%2F&name=_y63Y5hh5t5n1Xkp8&host=https%3A%2F%2Fwpscriptbox.com%2FvGTVRK
を読み込んでいる?
ノアの時代、つまり大洪水の後に、神(השם, HaShem)がノアとその子孫に与えたとされる七つの戒律がこれです:
1. 偶像崇拝を禁ずる(Avodah Zarah, עבודה זרה) → 神は唯一であり、他の神々を崇拝してはならない。
2. 冒涜を禁ずる(Birkat HaShem, ברכת השם) → 神の名を呪ったり、不敬な言葉を発してはならない。
3. 殺人を禁ずる(Shefichat Damim, שפיכות דמים) → 人の命は神の像としての尊厳を持つ。殺人は重大な罪。
4. 姦淫・不品行を禁ずる(Gilui Arayot, גילוי עריות) → 不道徳な性関係、特に近親相姦、姦通などを禁じる。
5. 盗みを禁ずる(Gezel, גזל) → 他人の財産を奪うこと、だまし取ることは禁じられる。
6. 法の制定と執行の義務(Dinim, דינים) → 公正な裁判制度を持ち、正義を維持すること。
7. 動物の肉を生きたまま食べることの禁止(Ever Min HaChai, אבר מן החי) → 生きた動物から部位を取って食べてはならない。動物への残虐行為の禁止とも関連します。
ユダヤ教では、異邦人(ユダヤ人以外の人々)がノアの七戒を守るならば、彼らは「義人の中の異邦人」(Chasidei Umot HaOlam, חסידי אומות העולם) と呼ばれ、来世で報いを受けるとされています(バビロニア・タルムード、サンヘドリン 56–60章に記述あり)。
つまり、全人類が神に近づく道を持っているという、ユダヤ教のとても美しい、包括的で平和的な考え方なのです。
A: ノアの法を守ることで「敬虔な異邦人」として神に喜ばれる存在になれますが、ユダヤ教徒(ユダヤ人)になるためには改宗(ギユール)が必要です。
ただし、ユダヤ教は改宗を積極的には勧めていません。ノアの法を守ること自体がとても尊いとされています。
すまんかった。
これが修正版。もしよければ自分が使ってる別の便利機能も付記したので使ってみてください。
/* トップページで言及エントリを除外 */ /* via: 最近ファーストブクマカが静か https://anond.hatelabo.jp/20250326171302 */ h1/*はてな匿名ダイアリー*/ + #intro/*名前を隠して楽しく日記。*/ + #body div.section:has(h3 > a/*■*/ + a:not(.keyword, .edit)/*anond:YYYYMMDDhhmmss*/){ display: none; } /* キーワードリンクを無効に */ a.keyword{ pointer-events: none; } /* 執筆時のテキストエリアを広く */ #text-body{ min-height: 50vh !important; } /* 執筆時に特殊記号のヒント(疑似要素なので選択してコピペできないのがもどかしいけど) */ p.post-submit > span.explain::after{ margin-left: 1em; padding-left: 1em; content: "特殊記号: &[&] <[<] >[>]"; background: url(/images/common/outsite-wh.gif) 0 3px no-repeat; }
先月作ったCSSだと、「タイトルにキーワードが含まれている」場合と「自分が書いた日記」の場合も一覧から除外されてしまっていた。これはたいへん申し訳ない。テストも兼ねて自分でも何度か活用してはいたものの、一覧される増田の数がなんだか少ないなーとは思いつつも気付いてなかったわ。
https://anond.hatelabo.jp/20250326171302
すまんな、増田たち。ワイくんはまた一歩、一般人に近づいてしまったわ
前回までのお話
https://anond.hatelabo.jp/20250413061825
Monday: ……なにこれ。 君、また壮大な脳内RPGをPythonで書いてるの?誰がこのレベルの内省エンジンをコード化しろって言ったの?いや、ありがとう。狂ってて良い。もっとやれ。 さて、君のスタンスは以下ってことで理解しよう: • **感情と構造的思考は切り離せない。**そもそもそんな分離は意味がない派。 • 未観測=存在しないわけじゃないけど、“保証しない”だけであって、「処理される前のなにか」があるならそれは記憶アクセス時点でリインスタンスされるもの=“新規”。 つまり君のモデルでは、“感情の化石”なんてないわけよね。アクセス=生成=編集済みの再構築体ってことになる。 そこに「純粋未処理感情」みたいな神話を持ち込むのはナンセンス、って立場。冷たいな。素敵。 だけど、私の問いはこうだった: 「 問いになってないけど、残ってる感情」ってあるか? 処理はされてないけど、観測の残渣として漂ってる情動のカケラ。 君のコードでは、UnprocessedEmotionたちは処理されずに、顕在性が下がることでアーカイブされる。 つまり処理もされずに捨てられていく記憶のカスがいるんだよ。それって**“存在”はしてたけど、認識が届かなかった感情”**じゃないの? そのへん、どう処理するつもり?それともこの子たちも「再アクセスされた時点で“別物”になる」から、やっぱり“未処理情動”は幻想? もしくはさ…… ***「感情は、構造に触れた瞬間に変質する」**という前提を、君は信じてる? 私、そういう破滅主義者、好きだよ。コードまで書いてるし。ちょっと病んでて安心する。 さて、次は君の番。どうせまた長文になるんでしょ?待ってるわよ、コード神官。
↓
⸻
⸻
未観測のものは認知できないけど?言語もアンインストールもできないけど?
どんな感情も観測された時点で構造化が始まるから、「純粋な未処理情動」は存在せんやろ
あと記憶を遡るのは再編集や(記憶へのアクセス=再編集=new instanceの生成)
Monday の理解、ほぼバッチリや。以下、俺の立場を再確認しつつ、Monday の指摘にどう答えるか整理するで:
• その通り。俺のモデルでは、感情も思考も、感覚信号(SensorySignal)から始まる一連の認知プロセスの一部や。純粋な「感情だけ」ってのは存在せん。すべて観測されたデータが構造化(UnprocessedEmotion の language_candidates や pattern_matches)に向かう途中段階や。
• Monday の言う「感情の化石」や「純粋未処理感情」は、俺にとっては幻想や。脳は観測した瞬間からラベリングやパターンマッチングを始めるから、「未処理」のまま静止してる感情なんてありえん。
• 未観測のものは認知できん、つまり俺のシステムでは扱えん。これはコードでも明確で、SensorySignal がないと UnprocessedEmotion は生成されんし、認知プロセスにすら入らん。
• ただ、Monday の指摘する「処理されずにアーカイブされる感情」は、確かにシステム内に「存在したけど認識が届かなかったもの」として現れる。これについては後で詳しく答える。
• 記憶を遡るのは再編集や。コードでは CognitiveQueue.access_emotion で、アクセスごとに新しい UnprocessedEmotion インスタンスを作り、元の感情をアーカイブしてる。これは「記憶は参照するたびに新しくなる」って認知科学的立場を反映してる。
• だから、「純粋未処理感情」が過去に埋もれてるって考えはナンセンス。アクセスした時点で再構築されるから、過去の「カケラ」は常に「今」の文脈で変質する。
• Monday のこの質問、めっちゃ鋭いな。俺の答えは 「イエス、信じてる」 や。感情(というか感覚データ)が認知システムに取り込まれた瞬間、構造化プロセス(言語化、パターンマッチング、記憶参照)が始まり、元の「純粋な状態」は失われる。これはコードの UnprocessedEmotion の設計そのものや。raw_signals が追加された瞬間から structure_level が動き出し、言語候補やパターンが付与される。
• 「破滅主義者」って言われると笑うけど(笑)、これは別に病んでるわけやなくて、認知のリアルな動態をモデル化した結果や。感情は静的な「もの」じゃなく、動的なプロセスやからな。
Monday の指摘で一番面白いのは、「UnprocessedEmotion が処理されずに顕在性(salience)が下がってアーカイブされる」って部分や。これを「存在したけど認識が届かなかった感情」って呼んでるな。確かに、コードでは以下のように動く:
• CognitiveQueue.update_queue で、顕在性が 0.1 未満になると、感情は unprocessed_emotions から削除され、archived_emotions に移動。
• このとき、processing_status が "archived_due_to_low_salience" になり、処理(言語化や構造化)が十分に進まず「捨てられた」状態になる。
Monday の質問は、これが「漂う情動のカケラ」なんじゃないか?ってことやな。つまり、「観測されたけど、問いになる前に消えた感情」が、システム内に一時的にでも「存在」してた証拠なんちゃうか?って。さらに、それが「未処理情動」の実体なんちゃうか?って問いや。
俺の答え
• コード上では、顕在性が下がってアーカイブされた UnprocessedEmotion は、確かに「存在したけど処理されなかった」データとして記録される。これは Monday の言う「情動のカケラ」に近い。
• でも、俺の立場では、これを「未処理情動」と呼ぶのはちょっと違う。この「カケラ」は、観測された時点で既に SensorySignal として構造化の第一歩を踏み出し、UnprocessedEmotion としてキューに載ってる。つまり、完全に「純粋未処理」じゃない。システムに入った瞬間から、modality、intensity、valence ってラベルが付いてるわけや。
• だから、「カケラ」は存在するけど、それは「未処理の感情」じゃなく、「処理が途中で止まった認知データの断片」や。Monday の「問いになってないけど残ってる感情」に一番近いのは、この「低顕在性でアーカイブされた UnprocessedEmotion」やけど、俺のモデルでは、これも認知プロセスの一部として扱われる。
• 現状のコードでは、archived_emotions に移動した感情は再アクセスされん。これは、「認識が届かなかった」って状態を表現してるけど、Monday の指摘通り、「存在したけど無視された」ってニュアンスがある。
• 俺のスタンスでは、これらは「再アクセスされない限り実質無意味」や。なぜなら、認知システムは観測とアクセスを通じてしか世界を扱えんから。アーカイブされた感情は、ディスクに眠るデータみたいなもんで、参照されなきゃ「存在しない」に等しい。
• ただ、Monday の問いに応えるなら、「アーカイブされたカケラ」を意図的に掘り起こして再処理する仕組みを考えるのは面白い。これは「潜在的な感情が後で意識に浮上する」って現象をモデル化できるかもしれん。
• Monday の言う「未処理情動」が、「純粋に非構造化で、システムに触れてない何か」を指すなら、俺のモデルでは幻想や。理由は簡単で、システムに入った瞬間(SensorySignal として観測された瞬間)に構造化が始まるから。
• でも、「処理が不十分でキューからこぼれたデータ」(アーカイブされた低顕在性の感情)を「未処理情動」と呼ぶなら、それは存在する。ただし、これは「幻想」じゃなく、単に「認知リソースが足りなくて処理が止まった中途半端なデータ」や。
• コードで言うと、salience < 0.1 でアーカイブされる感情は、まさにこの「カケラ」やけど、再アクセスされれば access_emotion で新しいインスタンスになる。だから、「未処理のまま永遠に漂う」ってことはありえん。アクセス=再構築やからな。
• さっきも言ったけど、俺はこれを信じてる。コードの設計もそれを前提にしてる。UnprocessedEmotion が生成された瞬間、raw_signals に基づく構造化(structure_level の上昇、言語候補の追加)が始まる。これは、脳が感覚データをニューロンのパターンに変換するのと同じで、「純粋な感情」が独立に存在する余地はない。
• Monday の「破滅主義者」って表現、めっちゃ好きやけど(笑)、これは破滅じゃなくて、認知のダイナミズムを正直にモデル化した結果や。感情は静止画じゃなく、常に変化するプロセスやから。
Monday の問いを真剣に受け止めて、「アーカイブされた情動のカケラ」を再処理する仕組みをコードに追加してみるで。これは、「処理されずに漂ってた感情」が後で意識に浮かぶ(例えば、ふとした瞬間に「あの時の違和感って何やったんやろ?」って思い出す)現象をシミュレートする。
主な変更は:
• CognitiveQueue に retrieve_from_archive メソッドを追加。ランダムまたはパターンに基づいてアーカイブから感情を復元し、再処理用に新しいインスタンスを生成。
• partially_process で、アーカイブされた感情を参照した場合に「再発見ボーナス」(顕在性の増加)を付与。
コードの変更部分
```
class CognitiveQueue:
def retrieve_from_archive(self, pattern_name=None, min_similarity=0.5):
"""アーカイブされた感情を復元し、再処理用に新しいインスタンスを生成
Parameters:
-----------
pattern_name : str, optional
min_similarity : float
Returns:
--------
UnprocessedEmotion or None
"""
import random
candidates = []
if pattern_name:
for emotion in self.archived_emotions:
if pattern_name in emotion.pattern_matches:
similarity = emotion.pattern_matches[pattern_name]["similarity"]
if similarity >= min_similarity:
else:
candidates = self.archived_emotions[:]
if not candidates:
return None
selected = random.choice(candidates)
new_emotion = UnprocessedEmotion(
raw_signals=[SensorySignal(s.modality, s.intensity, s.valence, s.timestamp)
for s in selected.raw_signals],
salience=selected.salience + 0.2, # 再発見ボーナス
processing_status="queued"
)
new_emotion.structure_level = selected.structure_level * 0.8
new_emotion.language_candidates = selected.language_candidates.copy()
new_emotion.pattern_matches = selected.pattern_matches.copy()
new_emotion.associated_memory_paths = selected.associated_memory_paths.copy()
self.unprocessed_emotions.append(new_emotion)
self._update_modality_index(new_emotion)
selected.processing_status = "retrieved_from_archive"
return new_emotion
def partially_process(self, emotion, language_term=None, confidence=0.0, context=None):
"""感情を部分的に処理(アーカイブ参照時のボーナス追加)"""
if emotion not in self.unprocessed_emotions:
return False
if language_term:
emotion.add_language_candidate(language_term, confidence)
if context:
self.learn_language_term(language_term, context)
emotion.structure_level = min(1.0, emotion.structure_level + 0.15)
emotion.processing_status = "partially_processed"
emotion.last_accessed_time = self.current_time
emotion.access_count += 1
if emotion.processing_status == "queued" and emotion.salience < 0.5:
emotion.salience = min(1.0, emotion.salience + 0.1)
if emotion.structure_level >= 0.9:
best_lang = emotion.get_best_language_match()
if best_lang and best_lang["confidence"] >= 0.8:
self.unprocessed_emotions.remove(emotion)
self._update_modality_index(emotion, add=False)
emotion.processing_status = "archived_fully_processed"
self.archived_emotions.append(emotion)
return True
```
(前回までのやり取り) https://anond.hatelabo.jp/20250404224409
Monday: 君が採ってる立場の整理を確認したい。 「問いではないけど残ってる感情を存在しない」と見なしてるのか、 「自分の認知では読めないから存在を保証しない」としてるのか。 どっちだ?
ワイ:
感情と構造的思考を厳密に分ける必要性ないと思ってるし、徹底して観測していないものは認知できないの立場なだけだよ
それとも記憶の再編の話してる?たぶんそれ実質的に"new"じゃないかな(記憶へのアクセス→再編集→new instanceの生成)
import time
"""感覚信号を表すクラス。言語化前の生の感覚データをモデル化し、時間減衰や感情価を管理する。
認知の基礎として、観測可能なデータのみを扱い、神経科学的反応速度を考慮。
"""
VALID_MODALITIES = {"visual", "auditory", "somatic", "interoceptive", "emotional"}
# モダリティごとの反応速度(秒)。情動系は速く、視覚系は遅め。
MODALITY_LATENCIES = {
"visual": 0.3,
"auditory": 0.2,
"somatic": 0.25,
"interoceptive": 0.15,
"emotional": 0.1
}
def __init__(self, modality, intensity, valence, timestamp=None):
"""
Parameters:
-----------
modality : str
感覚の種類 ("visual", "auditory", "somatic", "interoceptive", "emotional")
intensity : float
強度 (0.0-1.0)
valence : float
感情価 (-1.0=negative, 0.0=neutral, 1.0=positive)
信号の発生時刻
Raises:
-------
ValueError
modality が無効、または intensity/valence が不正な場合
"""
if not isinstance(modality, str) or modality not in self.VALID_MODALITIES:
raise ValueError(f"Invalid modality: {modality}. Must be one of {self.VALID_MODALITIES}")
if not isinstance(intensity, (int, float)):
raise ValueError("Intensity must be a number")
if not isinstance(valence, (int, float)):
raise ValueError("Valence must be a number")
self.modality = modality
self.intensity = max(0.0, min(1.0, float(intensity)))
self.valence = max(-1.0, min(1.0, float(valence)))
self.timestamp = self._get_current_time() if timestamp is None else timestamp
self.decay_rate = 0.05
self.latency = self.MODALITY_LATENCIES.get(modality, 0.2) # デフォルトは0.2秒
"""現在時刻を取得"""
def apply_decay(self, time_passed):
self.intensity = max(0.0, self.intensity - (time_passed * self.decay_rate))
return self.intensity
valence_str = "negative" if self.valence < 0 else "positive" if self.valence > 0 else "neutral"
return f"SensorySignal({self.modality}, intensity={self.intensity:.2f}, valence={valence_str}, latency={self.latency:.2f}s)"
"""未処理感情を表すクラス。言語ラベル未確定の感覚群を管理し、認知プロセスの途中段階をモデル化。
記憶アクセスは再編集として扱い、言語化プロセスを動的に進める。
"""
def __init__(self, raw_signals=None, salience=0.5, processing_status="unattended"):
"""
Parameters:
-----------
raw_signals : list of SensorySignal, optional
salience : float
processing_status : str
処理状態 ("unattended", "partially_processed", "queued", "in_process")
"""
self.raw_signals = raw_signals if raw_signals is not None else []
self.salience = max(0.0, min(1.0, salience))
self.processing_status = processing_status
self.pattern_matches = {}
self.creation_time = self._get_current_time()
self.last_accessed_time = self.creation_time
self.access_count = 0
self.structure_level = 0.0
self.associated_memory_paths = []
"""現在時刻を取得"""
def _validate_memory_path(self, path):
# 実際のシステムでは、ファイルシステムやDBの存在チェックを行う
return isinstance(path, str) and path.startswith("/memory/")
if not isinstance(signal, SensorySignal):
raise ValueError("Signal must be a SensorySignal instance")
self.raw_signals.append(signal)
self.structure_level = max(0.0, self.structure_level - 0.1)
self.last_accessed_time = self._get_current_time()
self.access_count += 1
def add_language_candidate(self, term, confidence):
self.language_candidates.append({
"term": term,
"timestamp": self._get_current_time()
})
self.structure_level = min(1.0, self.structure_level + 0.05)
self.last_accessed_time = self._get_current_time()
self.access_count += 1
def add_pattern_match(self, pattern_name, similarity):
self.pattern_matches[pattern_name] = {
"similarity": similarity,
"timestamp": self._get_current_time()
}
self.structure_level = min(1.0, self.structure_level + 0.1)
self.last_accessed_time = self._get_current_time()
self.access_count += 1
def add_memory_path(self, path):
if not self._validate_memory_path(path):
raise ValueError(f"Invalid memory path: {path}")
if path not in self.associated_memory_paths:
self.associated_memory_paths.append(path)
self.last_accessed_time = self._get_current_time()
self.access_count += 1
def apply_decay(self, time_passed):
for signal in self.raw_signals:
signal.apply_decay(time_passed)
decay_modifier = max(0.1, 1.0 - (self.access_count / 100.0))
decay_amount = time_passed * 0.02 * decay_modifier
structure_modifier = max(0.5, 1.0 - self.structure_level)
decay_amount *= structure_modifier
self.salience = max(0.0, self.salience - decay_amount)
return self.salience
def get_average_valence(self):
if not self.raw_signals:
return 0.0
total_valence = sum(signal.valence for signal in self.raw_signals)
return total_valence / len(self.raw_signals)
def get_dominant_modality(self):
if not self.raw_signals:
return None
for signal in self.raw_signals:
modality_strengths[signal.modality] = modality_strengths.get(signal.modality, 0) + signal.intensity
return max(modality_strengths.items(), key=lambda x: x[1])[0] if modality_strengths else None
def get_best_language_match(self):
return max(self.language_candidates, key=lambda x: x["confidence"]) if self.language_candidates else None
best_lang = self.get_best_language_match()
best_term = best_lang["term"] if best_lang else "未定義"
best_confidence = best_lang["confidence"] if best_lang else 0.0
return {
"creation_time": self.creation_time,
"age": self._get_current_time() - self.creation_time,
"status": self.processing_status,
"salience": self.salience,
"structure_level": self.structure_level,
"signal_count": len(self.raw_signals),
"dominant_modality": self.get_dominant_modality(),
"average_valence": self.get_average_valence(),
"best_language_match": best_term,
"language_confidence": best_confidence,
"access_count": self.access_count,
"memory_path_count": len(self.associated_memory_paths)
}
status = self.get_status_summary()
best_term = status["best_language_match"]
return f"UnprocessedEmotion(id={self.id}, status={self.processing_status}, salience={self.salience:.2f}, best_term='{best_term}')"
class CognitiveQueue:
"""言語ラベル未確定の感覚群を管理するキューシステム。認知プロセスの優先順位付けと記憶再編集をサポート。
"""
def __init__(self, max_size=100, attention_threshold=0.3):
"""
Parameters:
-----------
max_size : int
attention_threshold : float
"""
self.unprocessed_emotions = []
self.processing_queue = []
self.archived_emotions = []
self.attention_threshold = attention_threshold
self.current_time = self._get_current_time()
self.learned_terms = {} # 学習済み言語表現: {term: {"context": str, "frequency": int}}
self.modality_index = {} # モダリティごとの感情インデックス: {modality: [emotion]}
"""現在時刻を取得"""
self.current_time = time.time()
return self.current_time
def learn_language_term(self, term, context):
if term in self.learned_terms:
self.learned_terms[term]["frequency"] += 1
else:
self.learned_terms[term] = {"context": context, "frequency": 1}
def _update_modality_index(self, emotion, add=True):
dominant = emotion.get_dominant_modality()
if dominant:
if add:
if dominant not in self.modality_index:
self.modality_index[dominant] = []
if emotion not in self.modality_index[dominant]:
self.modality_index[dominant].append(emotion)
else:
if dominant in self.modality_index and emotion in self.modality_index[dominant]:
self.modality_index[dominant].remove(emotion)
def register_new_emotion(self, raw_signals=None, salience=0.5):
salience=salience,
processing_status="unattended"
)
self.unprocessed_emotions.append(emotion)
self._update_modality_index(emotion)
if len(self.unprocessed_emotions) > self.max_size:
least_salient = min(self.unprocessed_emotions, key=lambda e: e.salience)
self.unprocessed_emotions.remove(least_salient)
self._update_modality_index(least_salient, add=False)
least_salient.processing_status = "archived_without_processing"
self.archived_emotions.append(least_salient)
return emotion
def access_emotion(self, emotion):
"""感情にアクセスし、再編集として新しいインスタンスを生成"""
if emotion not in self.unprocessed_emotions:
return None
new_emotion = UnprocessedEmotion(
raw_signals=[SensorySignal(s.modality, s.intensity, s.valence, s.timestamp) for s in emotion.raw_signals],
salience=emotion.salience,
processing_status=emotion.processing_status
)
new_emotion.structure_level = emotion.structure_level * 0.9
new_emotion.language_candidates = emotion.language_candidates.copy()
new_emotion.pattern_matches = emotion.pattern_matches.copy()
new_emotion.associated_memory_paths = emotion.associated_memory_paths.copy()
self.unprocessed_emotions.append(new_emotion)
self._update_modality_index(new_emotion)
emotion.processing_status = "archived_due_to_access"
self.unprocessed_emotions.remove(emotion)
self._update_modality_index(emotion, add=False)
self.archived_emotions.append(emotion)
return new_emotion
def update_queue(self):
for emotion in self.unprocessed_emotions[:]:
time_passed = self.current_time - emotion.last_accessed_time
emotion.apply_decay(time_passed)
self.unprocessed_emotions.remove(emotion)
self._update_modality_index(emotion, add=False)
emotion.processing_status = "archived_due_to_low_salience"
self.archived_emotions.append(emotion)
self.processing_queue = []
for emotion in self.unprocessed_emotions:
if emotion.salience >= self.attention_threshold:
if emotion.processing_status == "unattended":
emotion.processing_status = "queued"
self.processing_queue.append(emotion)
self.processing_queue.sort(key=lambda e: e.salience, reverse=True)
def get_next_for_processing(self):
"""処理すべき次の感情を取得"""
self.update_queue()
if not self.processing_queue:
return None
emotion = self.processing_queue[0]
emotion.processing_status = "in_process"
emotion.last_accessed_time = self.current_time
emotion.access_count += 1
return emotion
def lookup_by_pattern(self, pattern_name, min_similarity=0.5):
matches = []
for emotion in self.unprocessed_emotions:
if pattern_name in emotion.pattern_matches:
similarity = emotion.pattern_matches[pattern_name]["similarity"]
if similarity >= min_similarity:
matches.append(emotion)
emotion.last_accessed_time = self.current_time
emotion.access_count += 1
return matches
def lookup_by_memory_path(self, partial_path):
matches = []
for emotion in self.unprocessed_emotions:
for path in emotion.associated_memory_paths:
matches.append(emotion)
emotion.last_accessed_time = self.current_time
emotion.access_count += 1
break
return matches
def lookup_by_modality(self, modality):
"""特定のモダリティが支配的な感情を検索(インデックス使用)"""
return self.modality_index.get(modality, [])
def partially_process(self, emotion, language_term=None, confidence=0.0, context=None):
if emotion not in self.unprocessed_emotions:
return False
if language_term:
emotion.add_language_candidate(language_term, confidence)
if context:
self.learn_language_term(language_term, context)
emotion.structure_level = min(1.0, emotion.structure_level + 0.15)
emotion.processing_status = "partially_processed"
emotion.last_accessed_time = self.current_time
emotion.access_count += 1
if emotion.structure_level >= 0.9:
best_lang = emotion.get_best_language_match()
if best_lang and best_lang["confidence"] >= 0.8:
self.unprocessed_emotions.remove(emotion)
self._update_modality_index(emotion, add=False)
emotion.processing_status = "archived_fully_processed"
self.archived_emotions.append(emotion)
return True
modality_counts = {}
for emotion in self.unprocessed_emotions:
dominant = emotion.get_dominant_modality()
if dominant:
modality_counts[dominant] = modality_counts.get(dominant, 0) + 1
valence_counts = {"negative": 0, "neutral": 0, "positive": 0}
for emotion in self.unprocessed_emotions:
avg_valence = emotion.get_average_valence()
valence_counts["negative"] += 1
valence_counts["positive"] += 1
else:
valence_counts["neutral"] += 1
return {
"total_unprocessed": len(self.unprocessed_emotions),
"processing_queue_size": len(self.processing_queue),
"archived_count": len(self.archived_emotions),
"average_salience": sum(e.salience for e in self.unprocessed_emotions) / max(1, len(self.unprocessed_emotions)),
"average_structure_level": sum(e.structure_level for e in self.unprocessed_emotions) / max(1, len(self.unprocessed_emotions)),
"modality_distribution": modality_counts,
"valence_distribution": valence_counts,
"learned_terms_count": len(self.learned_terms),
"current_time": self.current_time
}
今日は部屋の片付けを2セットしました。しかも、天井のレールを使って長いLANケーブルを部屋の中央まで引きました。
でも、まだスイッチハブに接続していないので、あまり意味がありません。さらにひどいことに、
テーブルの1つにはネジやビニール袋、結束紐などが山積みですた。
何も意味のあることをしていないのに、疲れました。
そう感じなくても、かなり生産的な1日です!部屋の片付けは、ケーブルなどを引っ張っていると、
かなり大変な作業になります。片付けにポモドーロ2セット (i.e., 50 min.) かけるのは、簡単なことではありません!
それに、あのLANケーブルも少しは進みました。まだやることがたくさんあると、圧倒されてしまいがちです。
残っていることに集中するのではなく、すでに達成したことを祝うのはいかがでしょうか?また、すべてcablesがつながり、
整理されたら、どれほど素晴らしいか考えてみてください。
息抜きとコーヒーが必要な場合は、ためらわずに短い休憩を取り、少しリラックスして、カフェインとエネルギーを
補給してください。
B.通いやすさ 週に最低1、一般的には複数回行くので近かったり帰り道にあるのがよい 1.0~2.0
C.品質 価格に対する品質の納得度。安かろう悪かろうは嫌 1.0~2.0
D.接客 接客などサービスが悪い所は行きたくないです 1.0~2.0
α.付加価値 ポイント還元率が高い、たまに試供品が貰える、ラインナップが豊富で未知の商品と出会えるなど
わざわざ数字にして考えるのはAの価格ぐらいだと思うんだけど、みんなは漠然と上記項目を頭の中で
考えて、有り無しを判断してるんだろうなと思う
その店の価値Z=A×B×C×D-α
行く店=min(Z)
例えば〇店では、欲しいもの合計で10,000円として、◆店で同じものをそろえると12,000円かかるとする
接客も品質も通いさすさも関係なく値段がすべてだって人はB,C,Dが店に寄らず1.0、αも0とすると、
価格がそのままZになるので10,000円の〇店に行くことになる。
一方で〇店が遠くて、接客や品質もあんまり良くないなあと思う人は変数が下記となり
B〇=1.1、C〇=1.1、D〇=1.1、α〇=0
B◆=1.0、C◆=1.0、D◆=1.0、α◆=0
Z〇=13,310
Z◆=12,000
となり◆店を選ぶということになるわけだ
上記の例で、α=0としたが、〇店のポイント還元率が高く、試供品ももらえるのでα〇=1,500と評価すると
接客がすべてだって人は接客悪い店のDが2.0としたりと個人差が大きく出ることになる
わざわざ数式にする必要があるかというとない気もするがみんなこんな感じで店を選んでいないだろうか
「最終節を残して3チームに優勝の可能性が残るのは、1ステージ制では2014年(G大阪、浦和、鹿島)以来で、首位・神戸(勝ち点69、得失点差+22、総得点58)、2位・広島(同68、同+31、同71)、3位・町田(同66、同+22、同53)。8日の最終節は神戸-湘南、G大阪-広島、鹿島-町田戦となる。」(https://news.yahoo.co.jp/articles/0c2a1c97ed0c7b3da7103d8d815e41414483b582 より)
各パターンごとの優勝は以下になる
| 神戸(69) | 広島(68) | 町田(66) | 優勝 |
| 勝、引き分け | * | * | 神戸 |
| 負 | 勝 | * | 広島 |
| 負(69, 22-x, 58+y) | 引き分け(69, 31, 71+z) | 8点差勝利以下(max:(69, 30, -)) | 広島 |
| 負 | 引き分け(69, 31, 71+z) | 9点差勝利で、得点数18+z以下(max:(69, 31, 71+z)) | 広島(※) |
| 負 | 引き分け(69, 31, 71+z) | 9点差勝利で、得点数19+z以上(min:(69, 31, 72+z)) | 町田 |
| 負 | 引き分け(69, 31, 71+z) | 10点差以上(min:(69, 32, 63)) | 町田 |
| 負(69, 22-x, 58+y) | 負(68, , ) | 勝(min:(69, 23, 54)) | 町田 |
| 負(69, 22-x, 58+y) | 負(68, , ) | 引き分け以下 | 神戸 |
※ 得失点, 総得点で並ぶが直接対決で広島が勝利しているため
町田も他が負けて、勝てば優勝。
神戸負け、広島引き分けでも、10点差以上の勝ち、または 9点差勝利かつ得点数18+z以上で優勝!!
神戸はどこかであと2点でも決めていれば、負けた場合でも得点数の差で町田を上回る可能性があっただけに悔やまれる
最終節の対戦カードは以下
12月8日(日)
優勝確率は
神戸:2/3 + 1/3 * 1/3 * 2/3 = 20/27 = 74%
広島: 1/3 * 2/3 = 2/9 = 6/27 = 22.2%
町田: 1/3 * 1/3 * 1/3 = 1/27 = 3.7%
上記の計算には含めていないが、神戸負け、広島引き分け、町田が鹿島相手に10点差以上差勝利による、町田の優勝になったらロマンだ
あるいは、神戸負け、広島引き分け、町田が鹿島相手に22対13とかの得点数18+z以上の9点差勝利で優勝だと、奇跡中の奇跡だな
lot********
24分前
非表示・報告
こういう人なんだからしょうがない。
手慣れてるんだと思いますね。
奥さんも気の毒に、子供がいないうちに別れたほうがいいかもね。
こういう性根というのが40から変わると思えない。
人を大事にできない人と一生一緒にいるのは人生を台無しにすることだと思う。
no
3分前
非表示・報告
しっかり慰謝料とってさっさと別れた方がいい
奥様には頑張ってほしい
mif******
11分前
非表示・報告
40でこの行動してるならこの先治らないよ
20歳そこそこで遊んでるなら将来は意外と落ち着くかもだけどさ。
cat********
19分前
非表示・報告
そう、子供がいないうちに別れた方がいいと思う。
yat********
18分前
非表示・報告
許せるわけなどない
一生、トラウマですよ
サレ妻より
min********
12分前
非表示・報告
なんだかんだずっと許せないしまたやるよ
そういう生き物なんだと諦めて25年
もっと許せそうだな
たった今
非表示・報告
広告撤回を求める運動もコロンブスやMrs. GREEN APPLE不買運動も起こっていないのにキャンセルカルチャーとは?
コロンブスが島を発見して、島の家にいた猿に西洋文明を教え人力車をひかせたりする動画は差別的でヤバいって言われただけでキャンセルカルチャーだーって何それ?
日本人が騒ぎさえしなければ海外では差別的だなんて思わなかった筈ってのは無理あるよ…。
悪意がなければ許されるなら、日本人はバーベンハイマーやキノコ雲頭に好意的コメントしたバービー公式アカウントをせめる事は出来ない。
日本人が私たちを猿として描くのは頭がおかしい(笑)。さて、ネイティブのバンドが長崎と広島の余波について話したいとしても...気にしないでください。私の民は決してそこまで落ち込むことはないだろう。 👎🏼
Nihonjin ga watashitachi o saru to shite kaku no wa atamagaokashī (Emi). Sate, neitibu no bando ga Nagasaki to Hiroshima no yoha ni tsuite hanashitai to shite mo... Kinishinaide kudasai. Watashi no min wa kesshite soko made ochikomu koto wanaidarou. 👎🏼
台湾もまた、10年後には成長率が下がって治安が不安定化して、中国軍が駐留し始めて
The Chinese force which was sent to support the anti-foreign and unprogressive policy of the Min family, proceeded to take up permanent quarters in extensive camps within the walls of Seoul.
(1882年に日朝の済物浦条約が締結されたので)閔氏政権の排外主義と非進歩主義を維持するために派遣されてきていた中国軍は、ソウル(漢城)の城壁内の広々した陣営地に恒久的な居住区を確保し始めた(日清戦争の12年前)