You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby数组相似元素索引校验:A/B计数逻辑错误排查与修复

猜数字游戏中A/B计数错误(重复元素处理问题)

问题描述

这是我在StackOverFlow上的第一个问题!如果问题表述不清,请告知我。

当前代码:

code = ["4", "4", "1", "1"]
guess = ["4", "4", "4", "1"]

@A = 0
@B = 0

code.each_with_index do |item, index|
  if item == guess[index]
    @A += 1 
  elsif code.include?(guess[index]) 
    @B += 1
  end
 print "\nA:#{@A} B:#{@B}"
end

需求:

  • 数字在两个数组相同索引位置 → @A加1
  • 数字存在于两个数组但索引不同 → @B加1

预期结果:A:3、B:0,实际得到A:3、B:1。code数组中没有第三个"4",所以@B不应加1。

疑问:是否是因为.include?无法正确处理数组中的重复元素?该如何修复?


问题原因

没错,问题就出在include?方法上——它只判断元素是否存在,完全不考虑数组中剩余可用的重复元素数量。

当遍历到guess的第三个元素"4"时,code里的两个"4"已经和guess的前两个"4"匹配成A了,没有多余的"4"可以用来计算B,但include?还是会返回true,导致错误地给B加1。


修复方案

方案一:统计元素频率(简洁高效)

通过统计两个数组中每个元素的出现次数,先计算总共有多少个元素是双方共有的,再减去已匹配位置的A数量,得到最终的B数量:

code = ["4", "4", "1", "1"]
guess = ["4", "4", "4", "1"]

# 计算A的数量:统计索引和元素都匹配的次数
a_count = code.each_with_index.count { |item, idx| item == guess[idx] }

# 统计两个数组中每个元素的出现频率
code_freq = code.tally
guess_freq = guess.tally

# 计算所有元素的最小出现次数之和(总共有多少个元素是双方共有的)
total_common = code_freq.keys.sum { |key| [code_freq[key], guess_freq[key] || 0].min }

# B的数量 = 总共有元素 - 已匹配位置的A数量
b_count = total_common - a_count

puts "A:#{a_count} B:#{b_count}" # 输出:A:3 B:0

方案二:标记并移除已匹配元素(直观易懂)

先标记出已经匹配成A的元素,再遍历剩余元素计算B,每匹配一个就移除对应元素避免重复计数:

code = ["4", "4", "1", "1"].dup # 复制数组,避免修改原数据
guess = ["4", "4", "4", "1"]

a_count = 0
b_count = 0

# 第一步:统计A,同时标记已匹配的元素
guess.each_with_index do |g_item, idx|
  if g_item == code[idx]
    a_count += 1
    code[idx] = nil # 标记为已匹配,后续不再参与B的计算
  end
end

# 第二步:统计B,只处理未匹配A的元素,且匹配后移除对应元素
guess.each_with_index do |g_item, idx|
  # 跳过已经匹配A的元素
  next if code[idx].nil?

  if code.include?(g_item)
    b_count += 1
    code[code.index(g_item)] = nil # 移除已匹配的元素,防止重复计算
  end
end

puts "A:#{a_count} B:#{b_count}" # 输出:A:3 B:0

内容的提问来源于stack exchange,提问作者hpm00

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 04:25:31