#include <iostream>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include<vector>
#include <bitset>
#include <algorithm>
#include <cmath>
#include <tuple>
#include <climits>
#include <stdlib.h>
#define ll long long
#define ull unsigned long long
#define mod 1000000007
typedef long double ld;
using namespace std;
#define forn(n) for(ll i=0;i<n;i++)
vector<ll> primeFactorize(ll n) 
{ 
	ll spf[n];
    spf[1] = 1; 
    for (ll  i=2; i<n; i++) 
  
        spf[i] = i; 

    for (int i=4; i<n; i+=2) 
        spf[i] = 2; 
  
    for (int i=3; i*i<n; i++) 
    { 

        if (spf[i] == i) 
        { 
            for (int j=i*i; j<n; j+=i) 
  
                if (spf[j]==j) 
                    spf[j] = i; 
        } 
    } 
 vector<ll> ret; 
    while (n != 1) 
    { 
        ret.push_back(spf[n]); 
        n= n / spf[n]; 
    } 
    return ret; 
} 
  


ll reverse(ll n)
{
	ll s=0;
	while(n>0)
	{
       ll t=n%10;
	   s=s*10+t;
	   n/=10;
	}
	return s;
}
int count_setbits(int N)

{ int cnt=0;

while(N>0)

{

cnt+=(N&1);

N=N>>1;

}

return cnt;

}
ll power(ll x, ll y)  
{  
    int res = 1;     // Initialize result  
  
    x = x % mod; // Update x if it is more than or  
                // equal to p 
   
    if (x == 0) return 0; // In case x is divisible by p; 
  
    while (y > 0)  
    {  
        // If y is odd, multiply x with result  
        if (y & 1)  
            res = (res*x) % mod;  
  
        // y must be even now  
        y = y>>1; // y = y/2  
        x = (x*x) % mod;  
    }  
    return res;  
}  

void BellmanFord(vector< vector<ll> > &graph, int V, int E, int src) 
{ 
    // Initialize distance of all vertices as infinite. 
    int dis[V]; 
    for (int i = 0; i < V; i++) 
        dis[i] = INT_MAX; 
  
    // initialize distance of source as 0 
    dis[src] = 0; 
  
    // Relax all edges |V| - 1 times. A simple 
    // shortest path from src to any other 
    // vertex can have at-most |V| - 1 edges 
    for (int i = 0; i < V - 1; i++) { 
  
        for (int j = 0; j < E; j++) { 
            if (dis[graph[j][0]] + graph[j][2] < 
                               dis[graph[j][1]]) 
                dis[graph[j][1]] =  
                  dis[graph[j][0]] + graph[j][2]; 
        } 
    } 
  
    // check for negative-weight cycles. 
    // The above step guarantees shortest 
    // distances if graph doesn't contain 
    // negative weight cycle.  If we get a 
    // shorter path, then there is a cycle. 
    for (int i = 0; i < E; i++) { 
        int x = graph[i][0]; 
        int y = graph[i][1]; 
        int weight = graph[i][2]; 
        if (dis[x] != INT_MAX && 
                   dis[x] + weight < dis[y]) 
            cout << "Graph contains negative"
                    " weight cycle"
                 << endl; 
    } 
  
    
} 

ll find_binary_rotated(vector<ll> &a,ll key)
{
 ll start=0;ll end=a.size()-1;
 while(start<=end)
 {
	 ll mid=(start+end)/2;
	 if(key==a[mid])
	 return mid;
	 else if(a[start]<=a[mid])
	 {
		 if(key>=a[start] && key<=a[mid])
		 end=mid-1;
		 else
		 {
			 start=mid+1;
		 }
		 
	 }
	 else
	 {
		 if(key>=a[mid] && key<=a[end])
		 start=mid+1;
		 else
		 {
			 end=mid-1;
		 }
		 
	 }
	 
 }
 return -1;
}


int main()
{
	
	
		
	char ch;
	cin>>ch;
	if(ch>='A' && ch<='Z')
	cout<<"A\n";
	else
	{
		cout<<"a\n";
	}
	
		

	


		

		
		
		

		
		
	
	
	


	
	
}

Measured memory_bytes: 3068