Go: package main

import (
	"bufio"
	"os"
	"strings"
	"fmt"
)

var scanner = bufio.NewScanner(os.Stdin)

func nextString() string {
	scanner.Scan()
	return scanner.Text()
}

func cipher(text string, direction int, int_shift int) string {
	shift, offset := rune(int_shift), rune(26)
	runes := []rune(text)
	for index, char := range runes {
		switch direction {
		case 1:
			if char >= 'a' && char <= 'z'-shift || char >= 'A' && char <= 'Z'-shift {
				char = char + shift
			} else if char > 'z'-shift && char <= 'z' || char > 'Z'-shift && char <= 'Z' {
				char = char + shift - offset
			}
		case -1:
			if char >= 'a'+shift && char <= 'z' || char >= 'A'+shift && char <= 'Z' {
				char = char - shift
			} else if char >= 'a' && char < 'a'+shift || char >= 'A' && char < 'A'+shift {
				char = char - shift + offset
			}
		}
		runes[index] = char
	}
	return string(runes)
}

func main() {
	for {
		infos := strings.Split(nextString(), " ")
		plain := make([]string, len(infos))
		if len(infos) == 0 {
			break
		}
		// println(infos)
		Decryption:
			for i := 0; i < 26; i++ {
				for j := range infos {
					plain[j] = cipher(infos[j], 1, i)
				}
				for j := range plain {
					if plain[j] == "this" || plain[j] == "that" || plain[j] == "the" {
						break Decryption
					}
				}
			}
			fmt.Println(strings.Join(plain, " "))
	}
}

C++: #include<iostream>
#include<string>

using namespace std;

int main() {
	string str, str2, ans;
	int i, j, l, n = 0;
	while (cin >> str) {
		ans += str;
		ans += ' ';
		if (n != 0) {
			continue;
		}
		l = str.length();
		str2.resize(l);
		for (i = 1; i < 26; i++) {
			for (j = 0; j < l; j++) {
				if (str[j] == '.') {
					continue;
				}
				if (str[j] + i > 'z') {
					str2[j] = str[j] - 26 + i;
				}
				else {
					str2[j] = str[j] + i;
				}
			}
			if (str2 == "the" || str2 == "the." || str2 == "this" || str2 == "this." || str2 == "that" || str2 == "that.") {
				n = i;
				break;
			}
		}
	}
	l = ans.length();
	ans.erase(l - 1);
	for (i = 0; i < l; i++) {
		if (ans[i] == '.' || ans[i] == ' ') {
			continue;
		}
		if (ans[i] + n > 'z') {
			ans[i] = ans[i] - 26 + n;
		}
		else {
			ans[i] = ans[i] + n;
		}
	}
	cout << ans << endl;
	return 0;
}

C++: #include <bits/stdc++.h>

#define rep(i, n) for (int i = 0; i < int(n); i++)
#define rrep(i, n) for (int i = int(n) - 1; i >= 0; i--)
#define reps(i, n) for (int i = 1; i <= int(n); i++)
#define rreps(i, n) for (int i = int(n); i >= 1; i--)
#define repc(i, n) for (int i = 0; i <= int(n); i++)
#define rrepc(i, n) for (int i = int(n); i >= 0; i--)
#define repi(i, a, b) for (int i = int(a); i < int(b); i++)
#define repic(i, a, b) for (int i = int(a); i <= int(b); i++)
#define each(x, y) for (auto &x : y)
#define all(a) (a).begin(), (a).end()
#define bit(b) (1ll << (b))

using namespace std;

using i32 = int;
using i64 = long long;
using u64 = unsigned long long;
using f80 = long double;
using vi32 = vector<i32>;
using vi64 = vector<i64>;
using vu64 = vector<u64>;
using vf80 = vector<f80>;
using vstr = vector<string>;

inline void yes() { cout << "Yes" << '\n'; exit(0); }
inline void no() { cout << "No" << '\n'; exit(0); }
inline i64 gcd(i64 a, i64 b) { if (min(a, b) == 0) return max(a, b); if (a % b == 0) return b; return gcd(b, a % b); }
inline i64 lcm(i64 a, i64 b) { return a / gcd(a, b) * b; }
inline u64 xorshift() { static u64 x = 88172645463325252ull; x = x ^ (x << 7); return x = x ^ (x >> 9); }
void solve(); int main() { ios::sync_with_stdio(0); cin.tie(0); cout << fixed << setprecision(16); solve(); return 0; }
template <typename T> class pqasc : public priority_queue<T, vector<T>, greater<T>> {};
template <typename T> class pqdesc : public priority_queue<T, vector<T>, less<T>> {};
template <typename T> inline void amax(T &x, T y) { if (x < y) x = y; }
template <typename T> inline void amin(T &x, T y) { if (x > y) x = y; }
template <typename T> inline T power(T x, i64 n, T e = 1) { T r = e; while (n > 0) { if (n & 1) r *= x; x *= x; n >>= 1; } return r; }
template <typename T> istream& operator>>(istream &is, vector<T> &v) { each(x, v) is >> x; return is; }
template <typename T> ostream& operator<<(ostream &os, vector<T> &v) { rep(i, v.size()) { if (i) os << ' '; os << v[i]; } return os; }
template <typename T, typename S> istream& operator>>(istream &is, pair<T, S> &p) { is >> p.first >> p.second; return is; }
template <typename T, typename S> ostream& operator<<(ostream &os, pair<T, S> &p) { os << p.first << ' ' << p.second; return os; }

void solve() {
  string s;
  while (getline(cin, s)) {
    rep(i, 26) {
      string t = s;
      map<char, char> ma;
      rep(j, 26) {
        char src = 'a' + j;
        char dst = 'a' + (j + i) % 26;
        ma[src] = dst;
      }
      int n = t.size();
      rep(j, n) {
        if (t[j] >= 'a' && t[j] <= 'z') t[j] = ma[t[j]];
      }
      bool f = false;
      for (int i = 0; i + 3 <= n; i++) {
        if (t.substr(i, 3) == "the") f = true;
      }
      for (int i = 0; i + 4 <= n; i++) {
        if (t.substr(i, 4) == "this") f = true;
      }
      for (int i = 0; i + 4 <= n; i++) {
        if (t.substr(i, 4) == "that") f = true;
      }
      if (f) {
        cout << t << '\n';
        break;
      }
    }
  }
}

C++: #include<iostream>
#include<stdio.h>
#include<string.h>
#include<ctype.h>

int main()
{
	char str[90];
	
	fgets( str, 81, stdin );
	
	while( 1 ){
		for( int i = 0; i < strlen( str ); i++ ){
			if( isalpha( str[i] ) ) str[i]++;
			
			if( str[i] > 'z' ){
			 	str[i] = 'a';
			}
		}
		
		if( strstr( str, "the" ) != NULL || strstr( str, "this" ) != NULL || strstr( str, "that" ) != NULL ) break;
	}
	
	std::cout << str << std::endl;

 	return 0;
}

C++: #include <iostream>
#include <string>
#include <algorithm>
#include <math.h>
#include <vector>
#include <set>

using namespace std;
typedef long long LL;
static const double EPS = 1e-9;

#define FOR(i,k,n) for (int i=(k); i<(int)(n); ++i)
#define REP(i,n) FOR(i,0,n) 

int main(void){  
  vector<string> words;
  string bf;
  int s = 0;
  while(cin>>bf) words.push_back(bf);
  REP(i,words.size()){
    REP(j,26){
      REP(k,words[i].size()){
        if(words[i][k] >= 'a' && words[i][k] <= 'z' )
        words[i].replace(k, 1, 1,
              'a' + ( words[i][k] + 1 - 'a')%('z'-'a'+1) );
        
        if(words[i] == "the"||words[i] == "this" || words[i] == "that" ||
           words[i] == "the." || words[i] == "this." || words[i] == "that." )
          s = j;
      }
    }
  }
  REP(i,words.size())
    REP(j,words[i].size())
      if(words[i][j] >= 'a' && words[i][j] <= 'z' )
        words[i].replace(j, 1, 1, 'a' + (words[i][j] + s+1 - 'a')%('z'-'a'+1) );
  cout << words[0];
  FOR(i,1,words.size())
    cout << " " << words[i];
}

C++: #define	_USE_MATH_DEFINES
#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cfloat>
#include <map>
#include <queue>
#include <stack>
#include <list>
#include <string>
#include <set>
using namespace std;
int main(){
	
	string s;
	while(getline(cin,s)){
		for(int i=0;i<26;i++){
			for(int j=0;j<s.size();j++){
				if(s[j]>='a'&&s[j]<='y'){
					s[j]++;
				}
				else if(s[j]=='z')
					s[j]='a';
			}
			if(s.find("the")!=string::npos||s.find("this")!=string::npos||s.find("that")!=string::npos){
				cout<<s<<endl;
				break;
			}
			
		}
	}
	
	
	
}