构建mod12整数全序列时如何避免内存溢出问题
生成ModN整数序列的内存优化方案
一、生成器实现(最优低内存方案)
直接将序列视为mod进制数,通过进制转换逐个生成序列,全程仅在内存中保留单个序列,彻底解决内存占用问题。
/** * 生成所有modN整数序列的生成器 * @param int $length 序列长度 * @param int $mod 模值(元素范围0~mod-1) * @return Generator 逐个返回序列数组 */ function melodyPatternsGenerator(int $length = 8, int $mod = 12) { $total = pow($mod, $length); for ($num = 0; $num < $total; $num++) { $pattern = []; $current = $num; // 从低位到高位转换为mod进制 for ($i = 0; $i < $length; $i++) { $pattern[] = $current % $mod; $current = intdiv($current, $mod); } // 反转得到从左到右的正常序列顺序 yield array_reverse($pattern); } } // 使用示例:边生成边筛选/输出 foreach (melodyPatternsGenerator(6, 12) as $pattern) { // 此处添加自定义筛选逻辑,例如: // if ($pattern[0] !== 0) continue; echo implode(' ', $pattern) . "\n"; }
该方案内存占用恒定(仅单个序列的内存),即使生成长度为10、mod=12的序列(12^10≈61亿个),也不会触发内存溢出,完全适配0.5GB内存限制。
二、原逻辑改造为生成器
若需保留“从全0逐步替换”的构建思路,可将原数组追加逻辑改为生成器,避免一次性存储所有序列:
function melodyPatternsOriginalGenerator(int $length = 8, int $mod = 12) { $initial = array_pad([], $length, 0); yield $initial; $prevPatterns = [$initial]; for ($i = 0; $i < $length; $i++) { $newBatch = []; foreach ($prevPatterns as $pattern) { for ($v = 1; $v < $mod; $v++) { $newPattern = $pattern; $newPattern[$i] = $v; $newBatch[] = $newPattern; yield $newPattern; } } $prevPatterns = array_merge($prevPatterns, $newBatch); } }
注:此方案需维护历史序列数组,内存占用会随迭代递增,但远低于原数组存储方案。
三、文件缓存方案
若需多次遍历或批量处理序列,可先将生成的序列写入临时文件,再逐行读取处理:
/** * 将所有序列写入文件 */ function writePatternsToFile(string $filePath, int $length = 8, int $mod = 12) { $handle = fopen($filePath, 'w'); foreach (melodyPatternsGenerator($length, $mod) as $pattern) { fwrite($handle, implode(' ', $pattern) . "\n"); } fclose($handle); } // 写入文件(长度6、mod12的序列约占30MB磁盘空间) writePatternsToFile('mod_sequences.txt', 6, 12); // 读取文件并处理 $handle = fopen('mod_sequences.txt', 'r'); while (($line = fgets($handle)) !== false) { $pattern = array_map('intval', explode(' ', trim($line))); // 自定义筛选或处理逻辑 } fclose($handle);
此方案适合需要持久化序列或多轮筛选的场景,磁盘占用远低于内存限制。
内容的提问来源于stack exchange,提问作者yarns
相关产品推荐
相关产品推荐

