#include <cctype>
#include <iostream>
#include<string>
#include<vector>
#include <algorithm>
using namespace std;
//合法的掩码可能出现的数字(前一后零)
int legelNum[9] = {255, 254, 252, 248, 240, 224, 192, 128, 0};
//分割字符串
void separate(const string str1, vector<string>& strvecIP,
vector<string>& strvecCode) {
//两遍相同操作分别把IP和掩码分割存储
string strIP = str1.substr(0, str1.find('~'));
int posl = 0, pos = strIP.find('.');
while (pos != string::npos) {
strvecIP.push_back(strIP.substr(posl, pos - posl));
posl = pos + 1;
pos = strIP.find('.',posl);
}
strvecIP.push_back(strIP.substr(posl));
//
string strCode = str1.substr(str1.find('~') + 1);
posl = 0, pos = strCode.find('.');
while (pos != string::npos) {
strvecCode.push_back(strCode.substr(posl, pos - posl));
posl = pos + 1;
pos = strCode.find('.',posl);
}
strvecCode.push_back(strCode.substr(posl));
}
//判断IP合法性
bool IPcorrection(const vector<string>strvecIP) {
//不合法情形只有分隔符间没数的情形
if (strvecIP.size() == 4) {
for (int i = 0; i < 4; i++) {
if (strvecIP[3 - i].size() == 0 || strvecIP[3 - i].size() > 3) {
return false;
}
}
}
return true;
}
//判断掩码合法性
bool Codecorrection(const vector<string>strvecCode) {
//如果IP地址是本网或者巡回自检,则即使掩码错了也不计入错误数,及其抽象,该判断放到main函数去了
if (strvecCode.size() != 4) {
return false;
}
else {
bool flag = true;//仅当第后面的数全为0时前面可能有不为255的数
for (int i = 0; i < 4; i++) {
if (strvecCode[i].size() == 0 || strvecCode[i].size() > 3) {
return false;//输入不合法的情形,没数或者超过255
} else {
if(stoi(strvecCode[0])==0||stoi(strvecCode[3])==255){
return false;//全0和全1的情形
}
if (flag) {
int num = stoi(strvecCode[3 - i]);
if (find(legelNum, legelNum + 9, num) != legelNum + 9) {
//判断数字合法
if (num != 0) {
flag = false;//不为0则前面必须全是255
}
}
else {
return false;//数字不合法
}
} else {
//后面已经有非0数了,前面必须全是255
if (stoi(strvecCode[3 - i]) != 255) {
return false;
}
}
}
}
}
return true;
}
//判断类别
int kind_Decide(const vector<string>strvecIP){
int num=stoi(strvecIP[0]);
if(1<=num&&num<=126){
return 0;
}
else if(128<=num&&num<=191){
return 1;
}
else if(192<=num&&num<=223){
return 2;
}
else if(224<=num&&num<=239){
return 3;
}
else if(240<=num&&num<=255){
return 4;
}
else{
return -1;//本网和巡回自检
}
}
//判断私网
bool private_Decide(const vector<string>strvecIP){
int num0=stoi(strvecIP[0]),num1=stoi(strvecIP[1]);
if(num0==10){
return true;
}
if(num0==172&16<=num1&&num1<=31){
return true;
}
if(num0==192&&num1==168){
return true;
}
return false;
}
int main() {
string str1;
int result[7]={0,0,0,0,0,0,0};
while (getline(cin, str1)) { // 注意 while 处理多个 case
vector<string>strvecIP,strvecCode;
separate(str1,strvecIP,strvecCode);
if(!IPcorrection(strvecIP)||!Codecorrection(strvecCode)&&stoi(strvecIP[0])!=0&&stoi(strvecIP[0])!=127){
result[5]++;
}
else{
if(kind_Decide(strvecIP)!=-1){
result[kind_Decide(strvecIP)]++;
}
if(private_Decide(strvecIP)){
result[6]++;
}
}
}
for(int i=0;i<7;i++){
cout << result[i] << ' ';
}
}