// JAY SHREE RAM!!
#include<bits/stdc++.h>
using namespace std;
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
//using namespace __gnu_pbds;
#define int long long int
#define cy cout << "YES" << endl
#define cn cout << "NO" << endl
#define c1 cout << "-1" << endl
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define maxi *max_element
#define mini *min_element
#define pb push_back
#define sz(x) (int)((x).size())
#define ff first
#define ss second
#define MOD 1000000007
//#const int inf 1e18+1
#define vi vector<int>
#define input(v) for(auto &item : v) cin >> item;
#define mod_add(a, b, m) (((a + b) % m) + m) % m
#define mod_mul(a, b, m) (((a * b) % m) + m) % m
#define mod_sub(a, b, m) (((a - b) % m) + m) % m
////#define ordered_set tree<int, null_type, less<int>,
// ---------------------------------------------------------------------------------------
bool cmp(pair<int,int> a, pair<int,int> b) {
if (a.first > b.first) {
return true;
} else if (a.first < b.first) {
return false;
} else {
return a.second < b.second;
}
}
bool isPrime(int n) {
for(int i = 2; i * i <= n; i++) {
if(n % i == 0) {
return false;
}
}
return true;
}
vi sieve(int n) {
vi prime;
vi vis(n + 1, 1);
vis[0] = vis[1] = 0;
for (int i = 2; i * i <= n; i++) {
if (vis[i]) {
for (int j = i * i; j <= n; j += i) {
vis[j] = 0;
}
}
}
for (int i = 2; i <= n; i++) {
if (vis[i]) {
prime.pb(i);
}
}
return prime;
}
int BinExp(int a, int b, int m) {
int ans = 1;
while (b > 0) {
if (b & 1) {
ans = (ans * 1LL * a) % m;
}
a = (a * 1LL * a) % m;
b >>= 1;
}
return ans;
}
// ----------------------------------------------------------------------------------------
void solve() {
// Your solution code goes here
int n,m,q;
cin>>n>>m>>q;
vector<vector<int>> arr(n,vector<int> (m,0));
/* for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
arr[i][j]=0;
}
}
*/
class Operation
{
public:
int type;
int row,col;
int val;
Operation(int t,int r,int c,int v)
{
type=t;
row=r;
col=c;
val=v;
}
};
vector<Operation> oper;
while(q--)
{
int type;
cin>>type;
if(type==1)
{
int r;cin>>r;
oper.pb({type,r-1,0,0});
}
else if(type==2)
{
int c;cin>>c;
oper.pb({type,0,c-1,0});
}
else
{
int r,c,x;
cin>>r>>c>>x;
oper.pb({type,r-1,c-1,x});
}
}
// q-1 se bhi kar sakte.. but while loop ke baad q would exhaust soo..
for(int i=sz(oper)-1;i>=0;i--)
{
Operation op=oper[i];
if(op.type==1)
{
int temp=arr[op.row][m-1];
// last ele ko store kiya
for(int j=m-1;j>0;j--)
{
arr[op.row][j]=arr[op.row][j-1];
}
arr[op.row][0]=temp; // first banane ke liye
// de circular shift xd
}
else if(op.type==2)
{
int temp=arr[n-1][op.col];
for(int j=n-1;j>0;j--)
{
arr[j][op.col]=arr[j-1][op.col];
}
arr[0][op.col]=temp;
}
else
{
arr[op.row][op.col]=op.val;
}
}
for(auto &it : arr)
{
for(auto & it1: it)
{
cout<<it1<<" ";
}
cout<<endl;
}
}
int32_t main() {
int t=1; //cin >> t;
while (t--) {
solve();
}
return 0;
}
698A - Vacations | 1216B - Shooting |
368B - Sereja and Suffixes | 1665C - Tree Infection |
1665D - GCD Guess | 29A - Spit Problem |
1097B - Petr and a Combination Lock | 92A - Chips |
1665B - Array Cloning Technique | 1665A - GCD vs LCM |
118D - Caesar's Legions | 1598A - Computer Game |
1605A - AM Deviation | 1461A - String Generation |
1585B - Array Eversion | 1661C - Water the Trees |
1459A - Red-Blue Shuffle | 1661B - Getting Zero |
1661A - Array Balancing | 1649B - Game of Ball Passing |
572A - Arrays | 1455A - Strange Functions |
1566B - MIN-MEX Cut | 678C - Joty and Chocolate |
1352E - Special Elements | 1520E - Arranging The Sheep |
1157E - Minimum Array | 1661D - Progressions Covering |
262A - Roma and Lucky Numbers | 1634B - Fortune Telling |