1. 字符串序列判定/最后一个有效字符
javascript
复制代码
const readline = require('readline');
// 创建一个readline接口对象来读取用户的输入
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
// 读取第一个字符串S
rl.on('line', (stringS) => {
// 读取第二个字符串L
rl.on('line', (stringL) => {
// 初始化两个索引,分别用于遍历S和L
let indexS = 0;
let indexL = 0;
// 当S和L都没有遍历完时,继续遍历
while (indexS < stringS.length && indexL < stringL.length) {
// 如果S中的当前字符与L中的当前字符相同,则S的索引加1
if (stringS.charAt(indexS) === stringL.charAt(indexL)) {
indexS++;
}
// 无论字符是否相同,L的索引都加1
indexL++;
}
// 如果S的所有字符都在L中找到了(即S已经遍历完了),则打印L中最后一个有效字符的位置(即L的当前索引减1)
if (indexS === stringS.length) console.log(indexL - 1);
// 如果S还有字符没有在L中找到,则打印-1
else console.log(-1);
rl.close();
});
});
2.山脉个数(逻辑)
javascript
复制代码
function count_peaks(hill_map) {
let count = 0; // 初始化计数器为 0
for(let i = 0; i < hill_map.length; i++){ // 遍历数组 hill_map
if(i === 0 && hill_map[i] > hill_map[i+1]){ // 如果当前位置在数组的开头,并且当前元素大于下一个元素
count++; // 计数器加一
}
if(i === hill_map.length-1 && hill_map[i] > hill_map[i-1]){ // 如果当前位置在数组的末尾,并且当前元素大于前一个元素
count++; // 计数器加一
}
if(i > 0 && i < hill_map.length-1 && hill_map[i] > hill_map[i-1] && hill_map[i] > hill_map[i+1]){ // 如果当前位置不在开头和末尾,并且当前元素大于前一个元素且大于后一个元素
count++; // 计数器加一
}
}
return count; // 返回计数器的值作为结果
}
3.构成指定长度的字符串的个数(去重排组合)
javascript
复制代码
// 导入所需的模块
const readline = require('readline');
// 创建一个接口来读取用户的输入
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
// 递归生成满足条件的不同字符串
function generateDistinctStrings(str, length, current, set, used) {
// 当生成的字符串长度等于指定长度时,将其加入到集合中
if (current.length === length) {
set.add(current);
return;
}
// 遍历字符串中的字符
for (let i = 0; i < str.length; i++) {
// 判断字符是否已经被使用,或者当前字符与前一个字符相同
if (used[i] || (current.length > 0 && current.charAt(current.length - 1) === str.charAt(i))) {
continue; // 如果字符已被使用或与前一个字符相同,则跳过当前字符
}
used[i] = true; // 标记当前字符为已使用
// 递归调用生成下一个字符
generateDistinctStrings(str, length, current + str.charAt(i), set, used);
used[i] = false; // 取消标记当前字符的使用状态,以便下一次遍历
}
}
// 计算满足条件的不同字符串的数量
function countDistinctStrings(str, length) {
// 创建一个集合来存储不同的字符串
const set = new Set();
// 创建一个数组来标记字符串中的字符是否已经被使用
const used = new Array(str.length).fill(false);
// 调用generateDistinctStrings方法生成满足条件的不同字符串
generateDistinctStrings(str, length, "", set, used);
// 打印生成的所有不同的字符串
// for (let string of set) {
// console.log(string);
// }
// 返回不同字符串的数量
return set.size;
}
// 读取用户输入的字符串
rl.on('line', (input) => {
// 将输入的字符串按空格分割为两部分,分别为字符串和长度
const parts = input.split(" ");
const str = parts[0]; // 获取输入的字符串
const length = parseInt(parts[1]); // 将输入的长度部分转换为整数
// 调用countDistinctStrings方法计算满足条件的不同字符串的数量
const count = countDistinctStrings(str, length);
// 输出计算结果
console.log(count);
rl.close();
});
4.用连续自然数之和来表达整数(滑动窗口)
javascript
复制代码
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
// 提示用户输入目标整数
rl.on('line', (target) => {
target = parseInt(target); // 将输入的字符串转换为整数
console.log(`${target}=${target}`);
let expressions = []; // 存储所有满足条件的表达式
// 遍历所有可能的起始自然数
for (let i = 1; i < target; i++) {
let sum = 0;
let expression = '';
// 从i开始累加,直到sum大于或等于target
for (let j = i; sum < target; j++) {
sum += j;
expression += `${j}+`; // 向表达式中添加自然数和加号
// 当累加和等于目标整数时,将表达式存储到数组中
if (sum === target) {
expressions.push(expression.slice(0, -1)); // 去掉表达式末尾的加号
break;
}
}
}
// 自定义比较函数,用于按表达式中自然数的个数进行排序
expressions.sort((a, b) => {
let aCount = a.split('+').length;
let bCount = b.split('+').length;
return aCount - bCount;
});
// 输出所有满足条件的表达式
expressions.forEach(expression => {
console.log(`${target}=${expression}`);
});
// 输出满足条件的表达式个数
console.log(`Result: ${expressions.length + 1}`);
rl.close();
});
5.全量和已占用字符集、字符串统计(逻辑)
javascript
复制代码
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.on('line', (input) => {
// 将输入字符串按照@符号分割为全量字符集和已占用字符集
const splitInput = input.split("@");
const fullCharacterSet = splitInput[0]; // 全量字符集
const occupiedCharacterSet = splitInput[1]; // 已占用字符集
// 创建字符列表,用于存储全量字符集中的字符及其对应的数量
const characterList = [];
// 将全量字符集按照逗号分割为单个字符
const fullCharacterSetSplit = fullCharacterSet.split(",");
// 遍历全量字符集的每个字符
for (const character of fullCharacterSetSplit) {
// 将字符按照冒号分割为字符和数量
const characterSplit = character.split(":");
characterList.push(characterSplit); // 将字符和数量添加到字符列表中
}
// 如果已占用字符集为空,则输出全量字符集
if (occupiedCharacterSet === "") {
console.log(fullCharacterSet + "@");
process.exit(0);
}
// 创建已占用字符集的哈希表,用于存储已占用字符及其对应的数量
const occupiedCharacters = {};
// 将已占用字符集按照逗号分割为单个字符
const occupiedCharacterSetSplit = occupiedCharacterSet.split(",");
// 遍历已占用字符集的每个字符
for (const character of occupiedCharacterSetSplit) {
// 将字符按照冒号分割为字符和数量
const characterSplit = character.split(":");
occupiedCharacters[characterSplit[0]] = parseInt(characterSplit[1]); // 将字符和数量添加到已占用字符集的哈希表中
}
// 遍历字符列表中的每个字符
for (let i = 0; i < characterList.length; i++) {
const character = characterList[i];
// 如果已占用字符集中包含当前字符
if (character[0] in occupiedCharacters) {
const count = parseInt(character[1]) - occupiedCharacters[character[0]]; // 计算剩余可用数量
if (count > 0) {
character[1] = count.toString(); // 更新字符列表中的数量为剩余可用数量
} else {
characterList.splice(i, 1); // 如果剩余可用数量为0,则移除当前字符
i--; // 由于移除了一个字符,需要将索引减1
}
}
}
// 构建输出字符串
let result = "";
for (const character of characterList) {
result += character[0] + ":" + character[1] + ","; // 将每个字符及其数量添加到输出字符串中
}
result = result.slice(0, -1); // 删除最后一个逗号
console.log(result); // 输出结果
rl.close();
});
6.密码输入检测(逻辑)
javascript
复制代码
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
readline.on('line', input => {
let result = '';
let isBig = false;
let isSmall = false;
let isNum = false;
let isSpec = false;
for (let c of input) {
if (c === '<') {
result = result.slice(0, -1);
} else {
result += c;
}
}
for (let c of result) {
if (/[0-9]/.test(c)) {
isNum = true;
} else if (/[a-z]/.test(c)) {
isSmall = true;
} else if (/[A-Z]/.test(c)) {
isBig = true;
} else {
isSpec = true;
}
}
let flagRes = result.length >= 8 && isNum && isSmall && isBig && isSpec;
console.log(result + "," + flagRes);
readline.close();
});
7.查找众数及中位数(逻辑)
javascript
复制代码
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.on('line', (input) => {
const numbers = input.split(" ").map(num => parseInt(num));
const countMap = new Map();
let maxCount = 0;
for (let number of numbers) {
let count = countMap.get(number) || 0;
count++;
countMap.set(number, count);
maxCount = Math.max(maxCount, count);
}
const maxCountNumbers = Array.from(countMap.entries())
.filter(entry => entry[1] === maxCount)
.map(entry => entry[0])
.sort((a, b) =>b - a);
let median;
if (maxCountNumbers.length % 2 !== 0) {
let index = Math.floor((maxCountNumbers.length + 1) / 2) - 1;
median = maxCountNumbers[index];
} else {
let index1 = maxCountNumbers.length / 2 - 1;
let index2 = maxCountNumbers.length / 2;
median = Math.floor((maxCountNumbers[index1] + maxCountNumbers[index2]) / 2);
}
console.log(median);
rl.close();
});
8.最长的指定瑕疵的元素子串(双指针)
javascript
复制代码
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.on('line', (line) => {
// 输入瑕疵度
const flaw = parseInt(line.trim());
// 输入字符串
rl.on('line', (line) => {
// 移除收尾空字符串
const s = line.trim();
// 定义元音字母集合
const vowels = new Set(['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U']);
// 记录字符串中所有元音字母的下标
const vowelIdxs = [];
for (let i = 0; i < s.length; i++) {
if (vowels.has(s.charAt(i))) {
vowelIdxs.push(i);
}
}
// 初始化双指针
let left = 0, right = 0 ;
// 记录所有满足瑕疵度的元音子串的长度
const lengths = [];
while (right < vowelIdxs.length) {
// 计算当前子串的瑕疵度
const lengthDiff = vowelIdxs[right] - vowelIdxs[left] - (right - left);
if (lengthDiff > flaw) {
// 如果瑕疵度超过了预期,左指针右移
left++;
} else {
// 如果瑕疵度不超过预期,记录子串长度
if (lengthDiff === flaw) {
lengths.push(vowelIdxs[right] - vowelIdxs[left] + 1);
}
// 右指针右移
right++;
}
}
// 如果没有满足瑕疵度的元音子串,输出 0
if (lengths.length === 0) {
console.log(0);
return;
}
// 输出最长的元音子串的长度
lengths.sort((a, b) => b - a);
console.log(lengths[0]);
});
});
9.整数最小和(逻辑)
javascript
复制代码
/*
* @Author: liwen liwen01@raxtone.com
* @Date: 2024-04-02 14:19:20
* @LastEditors: liwen liwen01@raxtone.com
* @LastEditTime: 2024-04-02 14:21:13
* @FilePath: \raxtone\Javasctipt\zhengshuzuixiaohe.js
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
const readline = require('readline');
// 创建readline接口实例
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.on('line', (array1Input) => {
// 将输入的字符串按空格分割为数组,并将每个元素转换为数字,然后去除第一个元素
const array1 = array1Input.split(' ').map(Number).slice(1);
rl.on('line', (array2Input) => {
// 将输入的字符串按空格分割为数组,并将每个元素转换为数字,然后去除第一个元素
const array2 = array2Input.split(' ').map(Number).slice(1);
rl.on('line', (kInput) => {
// 将输入的字符串转换为整数
const k = parseInt(kInput);
// 创建一个空数组pairsSum
const pairsSum = [];
// 嵌套循环,将array1和array2中的元素两两相加,并将结果存储到pairsSum中
for (const value1 of array1) {
for (const value2 of array2) {
pairsSum.push(value1 + value2);
}
}
// 对pairsSum中的元素进行排序
pairsSum.sort();
// 取出pairsSum中前k个元素,并使用reduce方法计算它们的和
const minSum = pairsSum.slice(0, k).reduce((sum, value) => sum + value, 0);
// 输出最小和
console.log(minSum);
// 关闭readline接口,结束程序的执行
rl.close();
});
});
});
10.找出作弊的人(排序比较)
javascript
复制代码
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
let input = [];
rl.on('line', (line) => {
input.push(line.trim());
}).on('close', () => {
// 读取员工的数量
const n = parseInt(input.shift());
// 创建一个数组用于存储员工的ID和分数
const employees = input.map(line => line.split(' ').map(Number));
// 按分数排序
employees.sort((a, b) => a[1] - b[1]);
let minDiff = Number.MAX_SAFE_INTEGER;
const pairs = [];
for (let i = 0; i < n - 1; i++) {
for (let j = i + 1; j < n; j++) {
const curDiff = employees[j][1] - employees[i][1];
if (curDiff < minDiff) {
pairs.length = 0; // 清空数组
minDiff = curDiff;
pairs.push({ id1: Math.min(employees[i][0], employees[j][0]), id2: Math.max(employees[i][0], employees[j][0]) });
} else if (curDiff === minDiff) {
pairs.push({ id1: Math.min(employees[i][0], employees[j][0]), id2: Math.max(employees[i][0], employees[j][0]) });
} else {
break;
}
}
}
// 对ID对进行排序
pairs.sort((a, b) => a.id1 - b.id1 || a.id2 - b.id2);
// 输出结果
pairs.forEach(pair => {
console.log(`${pair.id1} ${pair.id2}`);
});
});
11.找朋友(栈)
javascript
复制代码
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
let n = 0;
let height = [];
rl.on('line', (input) => {
if (!n) {
n = parseInt(input.trim());
} else {
height = input.trim().split(' ').map(Number);
let friendIndexes = new Array(n).fill(0);
let stack = [0];
for (let i = 1; i < n; i++) {
while (stack.length && height[i] > height[stack[stack.length - 1]]) {
friendIndexes[stack.pop()] = i;
}
stack.push(i);
}
let result = "";
for (let i = 0; i < n; i++) {
result += friendIndexes[i] + " ";
}
console.log(result.trim());
}
});
12.爱吃蟠桃的孙悟空(二分法)
javascript
复制代码
// 读取标准输入
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
// 判断以速度k是否能在h小时内吃完所有桃子
function canFinish(p, h, k) {
let ans = 0;
for (let x of p) {
ans += Math.ceil(x / k);
}
return ans <= h;
}
// 处理输入
rl.on('line', (input) => {
if (!this.peachCounts) {
// 第一行输入,转换为桃子数量数组
this.peachCounts = input.split(' ').map(Number);
return;
}
// 第二行输入,转换为小时数
const h = Number(input);
rl.close(); // 不再读取输入
// 输入验证
const n = this.peachCounts.length;
if (n === 0 || h <= 0 || n >= 10000 || h >= 10000 || n > h) {
console.log(0);
return;
}
// 二分查找最小吃桃速度
let left = 1, right = 1e9;
while (left < right) {
const mid = Math.floor((left + right) / 2);
if (canFinish(this.peachCounts, h, mid)) {
right = mid;
} else {
left = mid + 1;
}
}
// 输出最小吃桃速度
console.log(left);
});
13.游戏分组-王者荣耀(DFS)
javascript
复制代码
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
let res = Number.MAX_SAFE_INTEGER;
let totalSum = 0;
let targetSum = 0;
// 深度优先搜索函数
function dfs(nums, idx, count, currentSum) {
// 剪枝条件:如果当前总和超过目标,则停止 考友反馈,去掉可得100%
// if (currentSum > targetSum) return;
// 当我们为一个队伍选择了5名玩家时
if (count === 5) {
// 计算另一个队伍的总和
let otherTeamSum = totalSum - currentSum;
// 用较小的差值更新结果
res = Math.min(res, Math.abs(currentSum - otherTeamSum));
return;
}
// 如果我们已经考虑了所有玩家,停止递归
if (idx === 10) return;
// 为第一个队伍选择当前玩家
dfs(nums, idx + 1, count + 1, currentSum + nums[idx]);
// 不为第一个队伍选择当前玩家
dfs(nums, idx + 1, count, currentSum);
}
rl.on('line', (input) => {
let nums = input.split(' ').map(Number);
for (let num of nums) {
totalSum += num;
}
targetSum = totalSum / 2;
dfs(nums, 0, 0, 0);
console.log(res);
rl.close();
});
14.求满足条件的最长子串的长度(滑动窗口)
javascript
复制代码
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
// 读取输入的字符串
readline.on('line', (str) => {
// 初始化最长子串长度为-1
let maxLen = -1;
// 初始化一个标志,表示是否找到了包含字母的子串
let hasLetter = false;
// 初始化双指针l和r,分别表示子串的左右边界
let l = 0, r = 0;
// 创建一个双端队列用于存储字母的索引
let letterIdx = [];
// 遍历字符串
while (r < str.length) {
// 获取当前字符
let c = str.charAt(r);
// 如果当前字符是字母
if (c.match(/[a-zA-Z]/)) {
// 设置标志为true,表示找到了包含字母的子串
hasLetter = true;
// 将字母的索引添加到队列的尾部
letterIdx.push(r);
// 如果队列中有多于1个字母的索引
if (letterIdx.length > 1) {
// 移除队列头部的字母索引,并将左指针l移动到该索引的下一个位置
l = letterIdx.shift() + 1;
}
// 如果右指针r等于左指针l,跳过当前循环
if (r === l) {
r++;
continue;
}
}
// 更新最长子串长度
maxLen = Math.max(maxLen, r - l + 1);
// 移动右指针
r++;
}
// 如果没有找到包含字母的子串,输出-1
if (!hasLetter) {
console.log(-1);
} else {
// 否则输出最长子串长度
console.log(maxLen);
}
readline.close();
});
15. 分割均衡字符串(贪心)
javascript
复制代码
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.on('line', (s) => {
// 初始化变量,用于记录可分割成新的均衡子串的最大个数
let ans = 0;
// 初始化变量,用于记录当前位置字符'X'和'Y'的差值
let count = 0;
// 遍历字符串的每个字符
for (let i = 0; i < s.length; i++) {
// 判断当前字符是'X'还是'Y'
if (s.charAt(i) === 'X') {
// 如果是'X',则将count加1,表示出现了一个'X'
count++;
} else {
// 如果是'Y',则将count减1,表示出现了一个'Y'
count--;
}
// 在每次更新count后,判断count是否为0
if (count === 0) {
// 如果为0,表示当前位置可以作为分割点,将ans加1
ans++;
}
}
// 输出可分割成新的均衡子串的最大个数
console.log(ans);
rl.close();
});
16.机器人仓库搬砖(二分法)
javascript
复制代码
function minEnergyBlocks(bricks, hours) {
if (bricks.length > 8) { // 如果砖块数量大于8
return -1; // 返回-1
}
let left = 1, right = Math.max(...bricks); // 初始化左右边界
while (left < right) { // 二分查找
let middle = Math.floor((left + right) / 2); // 取中间值
let total_time = 0; // 计算当前能量块数量下能够搬完所有砖的总时间
for (let i = 0; i < bricks.length; i++) {
total_time += Math.ceil(bricks[i] / middle);
}
if (total_time > hours) { // 如果当前能量块数量下搬完所有砖的总时间超过了限定时间,缩小搜索范围
left = middle + 1;
} else { // 否则,减小能量块数量
right = middle;
}
}
let sum = 0;
for (let i = 0; i < bricks.length; i++) {
sum += Math.ceil(bricks[i] / left);
}
if (sum > hours) { // 检查最终确定的能量块数量是否能在规定时间内搬完所有砖
return -1; // 无法在规定时间内搬完所有砖
}
return left; // 返回最小能量块数量
}
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.on('line', (input) => {
const bricks = input.split(' ').map(Number);
console.log(minEnergyBlocks(bricks, 8)); // 调用函数并输出结果
rl.close();
});
17.出租车计费 、靠谱的车(逻辑)
javascript
复制代码
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.on('line', (line) => {
let correct = 0;
for (let i = 0; i < line.length; i++) {
let digit = parseInt(line[i]);
if (digit > 4) {
digit--;
}
correct = correct * 9 + digit;
}
console.log(correct);
});
18.开源项目热度榜单
javascript
复制代码
/*
* @Author: liwen liwen01@raxtone.com
* @Date: 2024-04-02 19:59:07
* @LastEditors: liwen liwen01@raxtone.com
* @LastEditTime: 2024-04-02 20:00:15
* @FilePath: \raxtone\Javasctipt\openproject.js
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
// 创建一个数组用于存储用户的输入
let input = [];
// 当接收到一行输入时,将其去除首尾空格后添加到input数组中
rl.on('line', (line) => {
input.push(line.trim());
}).on('close', () => { // 当输入结束时,执行以下代码
// 读取项目数量n
const n = parseInt(input[0]);
// 读取权重数组,将其转换为数字数组
const weights = input[1].split(' ').map(Number);
// 创建一个数组用于存储项目信息
let projects = [];
// 读取每个项目的信息
for (let i = 2; i < 2 + n; i++) {
// 将项目信息分割为名称和评分数组
const project = input[i].split(' ');
const name = project[0];
const scores = project.slice(1).map(Number);
// 计算项目的热度
let hotness = 0;
for (let j = 0; j < 5; j++) {
hotness += scores[j] * weights[j];
}
// 将项目的名称和热度添加到projects数组中
projects.push({ name, hotness });
}
// 对项目数组进行排序,首先根据热度降序排序,如果热度相同则根据名称升序排序
projects.sort((a, b) => {
if (a.hotness !== b.hotness) {
return b.hotness - a.hotness;
} else {
return a.name.localeCompare(b.name);
}
});
// 遍历排序后的项目数组并打印项目名称
for (let project of projects) {
console.log(project.name);
}
});
19.寻找身高相近的小朋友
javascript
复制代码
const readline = require('readline');
// 创建readline接口,用于读取输入
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
let h, n;
let heights = [];
// 监听输入事件
rl.on('line', (input) => {
// 如果h和n未赋值,表示当前输入为第一行,包含小明的身高和新班级其他小朋友的个数
if (!h && !n) {
const inputArr = input.split(' ');
h = parseInt(inputArr[0]);
n = parseInt(inputArr[1]);
} else {
// 否则,表示当前输入为第二行,包含其他小朋友的身高
const heightArr = input.split(' ');
// 将输入的身高字符串转换为整数并存储在heights数组中
heights = heightArr.map(height => parseInt(height));
// 对heights数组进行排序
heights.sort((a, b) => {
const diffA = Math.abs(a - h);
const diffB = Math.abs(b - h);
// 如果两个小朋友和小明身高差一样,则个子较小的小朋友排在前面
if (diffA === diffB) {
return a - b;
}
// 否则,根据与小明身高差的绝对值进行排序
return diffA - diffB;
});
// 输出排序后的结果
console.log(heights.join(' '));
}
});
20.考勤信息(逻辑)
javascript
复制代码
// 引入readline模块用于读取命令行输入
const readline = require('readline');
// 创建readline接口实例
const rl = readline.createInterface({
input: process.stdin, // 标准输入流
output: process.stdout // 标准输出流
});
// 定义函数判断是否能获得考勤奖
const canReceiveAward = (records) => {
let absentCount = 0; // 缺勤次数计数器
for (let i = 0; i < records.length; i++) {
if (records[i] === 'absent') { // 如果记录为缺勤
absentCount++; // 缺勤次数加1
if (absentCount > 1) return false; // 缺勤超过1次,返回false
}
if (records[i] === 'late' || records[i] === 'leaveearly') { // 如果记录为迟到或早退
// 如果前一天也是迟到或早退,返回false
if (i > 0 && (records[i - 1] === 'late' || records[i - 1] === 'leaveearly')) {
return false;
}
}
if (i >= 6) { // 检查任意连续7天的考勤记录
let countIn7Days = 0; // 连续7天内非正常上班的天数
for (let j = i - 6; j <= i; j++) {
if (records[j] !== 'present') { // 如果这7天内有非出勤记录
countIn7Days++;
}
}
if (countIn7Days > 3) return false; // 如果连续7天内非正常上班超过3天,返回false
}
}
return true; // 所有条件都满足,返回true
};
let lines = []; // 存储输入行的数组
// 监听命令行输入
rl.on('line', (line) => {
lines.push(line); // 将每行输入存储到lines数组中
}).on('close', () => { // 输入结束时触发
const testCases = parseInt(lines[0], 10); // 解析测试用例数量
for (let i = 1; i <= testCases; i++) { // 遍历每个测试用例
const attendanceRecords = lines[i].trim().split(" "); // 分割考勤记录
// 输出每个测试用例的结果,并根据条件添加空格分隔
process.stdout.write(canReceiveAward(attendanceRecords) ? "true" : "false");
if (i < testCases) {
process.stdout.write(" ");
}
}
process.exit(0); // 执行完毕后退出程序
});